|
@@ -153,9 +153,16 @@ static const struct pipe_buf_operations user_page_pipe_buf_ops = {
|
|
.get = generic_pipe_buf_get,
|
|
.get = generic_pipe_buf_get,
|
|
};
|
|
};
|
|
|
|
|
|
-/*
|
|
|
|
- * Pipe output worker. This fills a pipe with the information contained
|
|
|
|
- * from splice_pipe_desc().
|
|
|
|
|
|
+/**
|
|
|
|
+ * splice_to_pipe - fill passed data into a pipe
|
|
|
|
+ * @pipe: pipe to fill
|
|
|
|
+ * @spd: data to fill
|
|
|
|
+ *
|
|
|
|
+ * Description:
|
|
|
|
+ * @spd contains a map of pages and len/offset tupples, a long with
|
|
|
|
+ * the struct pipe_buf_operations associated with these pages. This
|
|
|
|
+ * function will link that data to the pipe.
|
|
|
|
+ *
|
|
*/
|
|
*/
|
|
ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
|
|
ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
|
|
struct splice_pipe_desc *spd)
|
|
struct splice_pipe_desc *spd)
|
|
@@ -280,11 +287,6 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
|
|
*/
|
|
*/
|
|
page_cache_readahead(mapping, &in->f_ra, in, index, nr_pages);
|
|
page_cache_readahead(mapping, &in->f_ra, in, index, nr_pages);
|
|
|
|
|
|
- /*
|
|
|
|
- * Now fill in the holes:
|
|
|
|
- */
|
|
|
|
- error = 0;
|
|
|
|
-
|
|
|
|
/*
|
|
/*
|
|
* Lookup the (hopefully) full range of pages we need.
|
|
* Lookup the (hopefully) full range of pages we need.
|
|
*/
|
|
*/
|
|
@@ -292,8 +294,9 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
|
|
|
|
|
|
/*
|
|
/*
|
|
* If find_get_pages_contig() returned fewer pages than we needed,
|
|
* If find_get_pages_contig() returned fewer pages than we needed,
|
|
- * allocate the rest.
|
|
|
|
|
|
+ * allocate the rest and fill in the holes.
|
|
*/
|
|
*/
|
|
|
|
+ error = 0;
|
|
index += spd.nr_pages;
|
|
index += spd.nr_pages;
|
|
while (spd.nr_pages < nr_pages) {
|
|
while (spd.nr_pages < nr_pages) {
|
|
/*
|
|
/*
|
|
@@ -455,11 +458,16 @@ fill_it:
|
|
/**
|
|
/**
|
|
* generic_file_splice_read - splice data from file to a pipe
|
|
* generic_file_splice_read - splice data from file to a pipe
|
|
* @in: file to splice from
|
|
* @in: file to splice from
|
|
|
|
+ * @ppos: position in @in
|
|
* @pipe: pipe to splice to
|
|
* @pipe: pipe to splice to
|
|
* @len: number of bytes to splice
|
|
* @len: number of bytes to splice
|
|
* @flags: splice modifier flags
|
|
* @flags: splice modifier flags
|
|
*
|
|
*
|
|
- * Will read pages from given file and fill them into a pipe.
|
|
|
|
|
|
+ * Description:
|
|
|
|
+ * Will read pages from given file and fill them into a pipe. Can be
|
|
|
|
+ * used as long as the address_space operations for the source implements
|
|
|
|
+ * a readpage() hook.
|
|
|
|
+ *
|
|
*/
|
|
*/
|
|
ssize_t generic_file_splice_read(struct file *in, loff_t *ppos,
|
|
ssize_t generic_file_splice_read(struct file *in, loff_t *ppos,
|
|
struct pipe_inode_info *pipe, size_t len,
|
|
struct pipe_inode_info *pipe, size_t len,
|
|
@@ -648,10 +656,18 @@ out_ret:
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
-/*
|
|
|
|
- * Pipe input worker. Most of this logic works like a regular pipe, the
|
|
|
|
- * key here is the 'actor' worker passed in that actually moves the data
|
|
|
|
- * to the wanted destination. See pipe_to_file/pipe_to_sendpage above.
|
|
|
|
|
|
+/**
|
|
|
|
+ * __splice_from_pipe - splice data from a pipe to given actor
|
|
|
|
+ * @pipe: pipe to splice from
|
|
|
|
+ * @sd: information to @actor
|
|
|
|
+ * @actor: handler that splices the data
|
|
|
|
+ *
|
|
|
|
+ * Description:
|
|
|
|
+ * This function does little more than loop over the pipe and call
|
|
|
|
+ * @actor to do the actual moving of a single struct pipe_buffer to
|
|
|
|
+ * the desired destination. See pipe_to_file, pipe_to_sendpage, or
|
|
|
|
+ * pipe_to_user.
|
|
|
|
+ *
|
|
*/
|
|
*/
|
|
ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, struct splice_desc *sd,
|
|
ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, struct splice_desc *sd,
|
|
splice_actor *actor)
|
|
splice_actor *actor)
|
|
@@ -744,6 +760,20 @@ ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, struct splice_desc *sd,
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(__splice_from_pipe);
|
|
EXPORT_SYMBOL(__splice_from_pipe);
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * splice_from_pipe - splice data from a pipe to a file
|
|
|
|
+ * @pipe: pipe to splice from
|
|
|
|
+ * @out: file to splice to
|
|
|
|
+ * @ppos: position in @out
|
|
|
|
+ * @len: how many bytes to splice
|
|
|
|
+ * @flags: splice modifier flags
|
|
|
|
+ * @actor: handler that splices the data
|
|
|
|
+ *
|
|
|
|
+ * Description:
|
|
|
|
+ * See __splice_from_pipe. This function locks the input and output inodes,
|
|
|
|
+ * otherwise it's identical to __splice_from_pipe().
|
|
|
|
+ *
|
|
|
|
+ */
|
|
ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out,
|
|
ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out,
|
|
loff_t *ppos, size_t len, unsigned int flags,
|
|
loff_t *ppos, size_t len, unsigned int flags,
|
|
splice_actor *actor)
|
|
splice_actor *actor)
|
|
@@ -774,12 +804,14 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out,
|
|
* generic_file_splice_write_nolock - generic_file_splice_write without mutexes
|
|
* generic_file_splice_write_nolock - generic_file_splice_write without mutexes
|
|
* @pipe: pipe info
|
|
* @pipe: pipe info
|
|
* @out: file to write to
|
|
* @out: file to write to
|
|
|
|
+ * @ppos: position in @out
|
|
* @len: number of bytes to splice
|
|
* @len: number of bytes to splice
|
|
* @flags: splice modifier flags
|
|
* @flags: splice modifier flags
|
|
*
|
|
*
|
|
- * Will either move or copy pages (determined by @flags options) from
|
|
|
|
- * the given pipe inode to the given file. The caller is responsible
|
|
|
|
- * for acquiring i_mutex on both inodes.
|
|
|
|
|
|
+ * Description:
|
|
|
|
+ * Will either move or copy pages (determined by @flags options) from
|
|
|
|
+ * the given pipe inode to the given file. The caller is responsible
|
|
|
|
+ * for acquiring i_mutex on both inodes.
|
|
*
|
|
*
|
|
*/
|
|
*/
|
|
ssize_t
|
|
ssize_t
|
|
@@ -831,11 +863,13 @@ EXPORT_SYMBOL(generic_file_splice_write_nolock);
|
|
* generic_file_splice_write - splice data from a pipe to a file
|
|
* generic_file_splice_write - splice data from a pipe to a file
|
|
* @pipe: pipe info
|
|
* @pipe: pipe info
|
|
* @out: file to write to
|
|
* @out: file to write to
|
|
|
|
+ * @ppos: position in @out
|
|
* @len: number of bytes to splice
|
|
* @len: number of bytes to splice
|
|
* @flags: splice modifier flags
|
|
* @flags: splice modifier flags
|
|
*
|
|
*
|
|
- * Will either move or copy pages (determined by @flags options) from
|
|
|
|
- * the given pipe inode to the given file.
|
|
|
|
|
|
+ * Description:
|
|
|
|
+ * Will either move or copy pages (determined by @flags options) from
|
|
|
|
+ * the given pipe inode to the given file.
|
|
*
|
|
*
|
|
*/
|
|
*/
|
|
ssize_t
|
|
ssize_t
|
|
@@ -886,13 +920,15 @@ EXPORT_SYMBOL(generic_file_splice_write);
|
|
|
|
|
|
/**
|
|
/**
|
|
* generic_splice_sendpage - splice data from a pipe to a socket
|
|
* generic_splice_sendpage - splice data from a pipe to a socket
|
|
- * @inode: pipe inode
|
|
|
|
|
|
+ * @pipe: pipe to splice from
|
|
* @out: socket to write to
|
|
* @out: socket to write to
|
|
|
|
+ * @ppos: position in @out
|
|
* @len: number of bytes to splice
|
|
* @len: number of bytes to splice
|
|
* @flags: splice modifier flags
|
|
* @flags: splice modifier flags
|
|
*
|
|
*
|
|
- * Will send @len bytes from the pipe to a network socket. No data copying
|
|
|
|
- * is involved.
|
|
|
|
|
|
+ * Description:
|
|
|
|
+ * Will send @len bytes from the pipe to a network socket. No data copying
|
|
|
|
+ * is involved.
|
|
*
|
|
*
|
|
*/
|
|
*/
|
|
ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe, struct file *out,
|
|
ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe, struct file *out,
|
|
@@ -946,8 +982,18 @@ static long do_splice_to(struct file *in, loff_t *ppos,
|
|
return in->f_op->splice_read(in, ppos, pipe, len, flags);
|
|
return in->f_op->splice_read(in, ppos, pipe, len, flags);
|
|
}
|
|
}
|
|
|
|
|
|
-/*
|
|
|
|
- * Splices from an input file to an actor, using a 'direct' pipe.
|
|
|
|
|
|
+/**
|
|
|
|
+ * splice_direct_to_actor - splices data directly between two non-pipes
|
|
|
|
+ * @in: file to splice from
|
|
|
|
+ * @sd: actor information on where to splice to
|
|
|
|
+ * @actor: handles the data splicing
|
|
|
|
+ *
|
|
|
|
+ * Description:
|
|
|
|
+ * This is a special case helper to splice directly between two
|
|
|
|
+ * points, without requiring an explicit pipe. Internally an allocated
|
|
|
|
+ * pipe is cached in the process, and reused during the life time of
|
|
|
|
+ * that process.
|
|
|
|
+ *
|
|
*/
|
|
*/
|
|
ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
|
|
ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
|
|
splice_direct_actor *actor)
|
|
splice_direct_actor *actor)
|
|
@@ -1077,6 +1123,21 @@ static int direct_splice_actor(struct pipe_inode_info *pipe,
|
|
return do_splice_from(pipe, file, &sd->pos, sd->total_len, sd->flags);
|
|
return do_splice_from(pipe, file, &sd->pos, sd->total_len, sd->flags);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * do_splice_direct - splices data directly between two files
|
|
|
|
+ * @in: file to splice from
|
|
|
|
+ * @ppos: input file offset
|
|
|
|
+ * @out: file to splice to
|
|
|
|
+ * @len: number of bytes to splice
|
|
|
|
+ * @flags: splice modifier flags
|
|
|
|
+ *
|
|
|
|
+ * Description:
|
|
|
|
+ * For use by do_sendfile(). splice can easily emulate sendfile, but
|
|
|
|
+ * doing it in the application would incur an extra system call
|
|
|
|
+ * (splice in + splice out, as compared to just sendfile()). So this helper
|
|
|
|
+ * can splice directly through a process-private pipe.
|
|
|
|
+ *
|
|
|
|
+ */
|
|
long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
|
|
long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
|
|
size_t len, unsigned int flags)
|
|
size_t len, unsigned int flags)
|
|
{
|
|
{
|