diff options
author | Jens Axboe <axboe@suse.de> | 2006-04-02 17:05:09 -0400 |
---|---|---|
committer | Jens Axboe <axboe@suse.de> | 2006-04-02 17:05:09 -0400 |
commit | 83f9135bddffded9f1716519b6c147bcf046c87e (patch) | |
tree | 24ed3b7e21cda62ff2a1947d04a1333066a5bc65 | |
parent | 4f6f0bd2ffa4e31c3524f5e65c84a29b6ab73307 (diff) |
[PATCH] splice: add comments documenting more of the code
Hopefully this will make Andrew a little more happy.
Signed-off-by: Jens Axboe <axboe@suse.de>
-rw-r--r-- | fs/splice.c | 70 |
1 files changed, 66 insertions, 4 deletions
diff --git a/fs/splice.c b/fs/splice.c index 07f4d863c2d4..34591924c783 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
@@ -37,6 +37,12 @@ struct splice_desc { | |||
37 | loff_t pos; /* file position */ | 37 | loff_t pos; /* file position */ |
38 | }; | 38 | }; |
39 | 39 | ||
40 | /* | ||
41 | * Attempt to steal a page from a pipe buffer. This should perhaps go into | ||
42 | * a vm helper function, it's already simplified quite a bit by the | ||
43 | * addition of remove_mapping(). If success is returned, the caller may | ||
44 | * attempt to reuse this page for another destination. | ||
45 | */ | ||
40 | static int page_cache_pipe_buf_steal(struct pipe_inode_info *info, | 46 | static int page_cache_pipe_buf_steal(struct pipe_inode_info *info, |
41 | struct pipe_buffer *buf) | 47 | struct pipe_buffer *buf) |
42 | { | 48 | { |
@@ -108,6 +114,10 @@ static struct pipe_buf_operations page_cache_pipe_buf_ops = { | |||
108 | .steal = page_cache_pipe_buf_steal, | 114 | .steal = page_cache_pipe_buf_steal, |
109 | }; | 115 | }; |
110 | 116 | ||
117 | /* | ||
118 | * Pipe output worker. This sets up our pipe format with the page cache | ||
119 | * pipe buffer operations. Otherwise very similar to the regular pipe_writev(). | ||
120 | */ | ||
111 | static ssize_t move_to_pipe(struct inode *inode, struct page **pages, | 121 | static ssize_t move_to_pipe(struct inode *inode, struct page **pages, |
112 | int nr_pages, unsigned long offset, | 122 | int nr_pages, unsigned long offset, |
113 | unsigned long len, unsigned int flags) | 123 | unsigned long len, unsigned int flags) |
@@ -292,6 +302,16 @@ splice_them: | |||
292 | return move_to_pipe(pipe, pages, i, offset, len, flags); | 302 | return move_to_pipe(pipe, pages, i, offset, len, flags); |
293 | } | 303 | } |
294 | 304 | ||
305 | /** | ||
306 | * generic_file_splice_read - splice data from file to a pipe | ||
307 | * @in: file to splice from | ||
308 | * @pipe: pipe to splice to | ||
309 | * @len: number of bytes to splice | ||
310 | * @flags: splice modifier flags | ||
311 | * | ||
312 | * Will read pages from given file and fill them into a pipe. | ||
313 | * | ||
314 | */ | ||
295 | ssize_t generic_file_splice_read(struct file *in, struct inode *pipe, | 315 | ssize_t generic_file_splice_read(struct file *in, struct inode *pipe, |
296 | size_t len, unsigned int flags) | 316 | size_t len, unsigned int flags) |
297 | { | 317 | { |
@@ -370,10 +390,12 @@ static int pipe_to_sendpage(struct pipe_inode_info *info, | |||
370 | * - Destination page does not exist, we can add the pipe page to | 390 | * - Destination page does not exist, we can add the pipe page to |
371 | * the page cache and avoid the copy. | 391 | * the page cache and avoid the copy. |
372 | * | 392 | * |
373 | * For now we just do the slower thing and always copy pages over, it's | 393 | * If asked to move pages to the output file (SPLICE_F_MOVE is set in |
374 | * easier than migrating pages from the pipe to the target file. For the | 394 | * sd->flags), we attempt to migrate pages from the pipe to the output |
375 | * case of doing file | file splicing, the migrate approach had some LRU | 395 | * file address space page cache. This is possible if no one else has |
376 | * nastiness... | 396 | * the pipe page referenced outside of the pipe and page cache. If |
397 | * SPLICE_F_MOVE isn't set, or we cannot move the page, we simply create | ||
398 | * a new page in the output file page cache and fill/dirty that. | ||
377 | */ | 399 | */ |
378 | static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf, | 400 | static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf, |
379 | struct splice_desc *sd) | 401 | struct splice_desc *sd) |
@@ -401,6 +423,10 @@ static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf, | |||
401 | * reuse buf page, if SPLICE_F_MOVE is set | 423 | * reuse buf page, if SPLICE_F_MOVE is set |
402 | */ | 424 | */ |
403 | if (sd->flags & SPLICE_F_MOVE) { | 425 | if (sd->flags & SPLICE_F_MOVE) { |
426 | /* | ||
427 | * If steal succeeds, buf->page is now pruned from the vm | ||
428 | * side (LRU and page cache) and we can reuse it. | ||
429 | */ | ||
404 | if (buf->ops->steal(info, buf)) | 430 | if (buf->ops->steal(info, buf)) |
405 | goto find_page; | 431 | goto find_page; |
406 | 432 | ||
@@ -484,6 +510,11 @@ out: | |||
484 | typedef int (splice_actor)(struct pipe_inode_info *, struct pipe_buffer *, | 510 | typedef int (splice_actor)(struct pipe_inode_info *, struct pipe_buffer *, |
485 | struct splice_desc *); | 511 | struct splice_desc *); |
486 | 512 | ||
513 | /* | ||
514 | * Pipe input worker. Most of this logic works like a regular pipe, the | ||
515 | * key here is the 'actor' worker passed in that actually moves the data | ||
516 | * to the wanted destination. See pipe_to_file/pipe_to_sendpage above. | ||
517 | */ | ||
487 | static ssize_t move_from_pipe(struct inode *inode, struct file *out, | 518 | static ssize_t move_from_pipe(struct inode *inode, struct file *out, |
488 | size_t len, unsigned int flags, | 519 | size_t len, unsigned int flags, |
489 | splice_actor *actor) | 520 | splice_actor *actor) |
@@ -585,6 +616,17 @@ static ssize_t move_from_pipe(struct inode *inode, struct file *out, | |||
585 | 616 | ||
586 | } | 617 | } |
587 | 618 | ||
619 | /** | ||
620 | * generic_file_splice_write - splice data from a pipe to a file | ||
621 | * @inode: pipe inode | ||
622 | * @out: file to write to | ||
623 | * @len: number of bytes to splice | ||
624 | * @flags: splice modifier flags | ||
625 | * | ||
626 | * Will either move or copy pages (determined by @flags options) from | ||
627 | * the given pipe inode to the given file. | ||
628 | * | ||
629 | */ | ||
588 | ssize_t generic_file_splice_write(struct inode *inode, struct file *out, | 630 | ssize_t generic_file_splice_write(struct inode *inode, struct file *out, |
589 | size_t len, unsigned int flags) | 631 | size_t len, unsigned int flags) |
590 | { | 632 | { |
@@ -611,6 +653,17 @@ ssize_t generic_file_splice_write(struct inode *inode, struct file *out, | |||
611 | return ret; | 653 | return ret; |
612 | } | 654 | } |
613 | 655 | ||
656 | /** | ||
657 | * generic_splice_sendpage - splice data from a pipe to a socket | ||
658 | * @inode: pipe inode | ||
659 | * @out: socket to write to | ||
660 | * @len: number of bytes to splice | ||
661 | * @flags: splice modifier flags | ||
662 | * | ||
663 | * Will send @len bytes from the pipe to a network socket. No data copying | ||
664 | * is involved. | ||
665 | * | ||
666 | */ | ||
614 | ssize_t generic_splice_sendpage(struct inode *inode, struct file *out, | 667 | ssize_t generic_splice_sendpage(struct inode *inode, struct file *out, |
615 | size_t len, unsigned int flags) | 668 | size_t len, unsigned int flags) |
616 | { | 669 | { |
@@ -620,6 +673,9 @@ ssize_t generic_splice_sendpage(struct inode *inode, struct file *out, | |||
620 | EXPORT_SYMBOL(generic_file_splice_write); | 673 | EXPORT_SYMBOL(generic_file_splice_write); |
621 | EXPORT_SYMBOL(generic_file_splice_read); | 674 | EXPORT_SYMBOL(generic_file_splice_read); |
622 | 675 | ||
676 | /* | ||
677 | * Attempt to initiate a splice from pipe to file. | ||
678 | */ | ||
623 | static long do_splice_from(struct inode *pipe, struct file *out, size_t len, | 679 | static long do_splice_from(struct inode *pipe, struct file *out, size_t len, |
624 | unsigned int flags) | 680 | unsigned int flags) |
625 | { | 681 | { |
@@ -640,6 +696,9 @@ static long do_splice_from(struct inode *pipe, struct file *out, size_t len, | |||
640 | return out->f_op->splice_write(pipe, out, len, flags); | 696 | return out->f_op->splice_write(pipe, out, len, flags); |
641 | } | 697 | } |
642 | 698 | ||
699 | /* | ||
700 | * Attempt to initiate a splice from a file to a pipe. | ||
701 | */ | ||
643 | static long do_splice_to(struct file *in, struct inode *pipe, size_t len, | 702 | static long do_splice_to(struct file *in, struct inode *pipe, size_t len, |
644 | unsigned int flags) | 703 | unsigned int flags) |
645 | { | 704 | { |
@@ -668,6 +727,9 @@ static long do_splice_to(struct file *in, struct inode *pipe, size_t len, | |||
668 | return in->f_op->splice_read(in, pipe, len, flags); | 727 | return in->f_op->splice_read(in, pipe, len, flags); |
669 | } | 728 | } |
670 | 729 | ||
730 | /* | ||
731 | * Determine where to splice to/from. | ||
732 | */ | ||
671 | static long do_splice(struct file *in, struct file *out, size_t len, | 733 | static long do_splice(struct file *in, struct file *out, size_t len, |
672 | unsigned int flags) | 734 | unsigned int flags) |
673 | { | 735 | { |