diff options
| -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 | { |
