diff options
| author | Jens Axboe <axboe@suse.de> | 2006-04-11 08:57:50 -0400 |
|---|---|---|
| committer | Jens Axboe <axboe@nelson.home.kernel.dk> | 2006-04-11 09:47:07 -0400 |
| commit | cbb7e577e732f576b9f399bc2600bdc0626c68dc (patch) | |
| tree | 55e3d65c9d9fb5b0ee25d0ccabf951de6da2db7b | |
| parent | 2514395ef88b46e895726a8d40966cb83de7940c (diff) | |
[PATCH] splice: pass offset around for ->splice_read() and ->splice_write()
We need not use ->f_pos as the offset for the file input/output. If the
user passed an offset pointer in through sys_splice(), just use that and
leave ->f_pos alone.
Signed-off-by: Jens Axboe <axboe@suse.de>
| -rw-r--r-- | fs/splice.c | 86 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_file.c | 12 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_lrw.c | 14 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_lrw.h | 4 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_vnode.h | 12 | ||||
| -rw-r--r-- | include/linux/fs.h | 12 |
6 files changed, 74 insertions, 66 deletions
diff --git a/fs/splice.c b/fs/splice.c index e50a460239..5d3eda6470 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
| @@ -231,8 +231,9 @@ static ssize_t move_to_pipe(struct pipe_inode_info *pipe, struct page **pages, | |||
| 231 | } | 231 | } |
| 232 | 232 | ||
| 233 | static int | 233 | static int |
| 234 | __generic_file_splice_read(struct file *in, struct pipe_inode_info *pipe, | 234 | __generic_file_splice_read(struct file *in, loff_t *ppos, |
| 235 | size_t len, unsigned int flags) | 235 | struct pipe_inode_info *pipe, size_t len, |
| 236 | unsigned int flags) | ||
| 236 | { | 237 | { |
| 237 | struct address_space *mapping = in->f_mapping; | 238 | struct address_space *mapping = in->f_mapping; |
| 238 | unsigned int offset, nr_pages; | 239 | unsigned int offset, nr_pages; |
| @@ -241,8 +242,8 @@ __generic_file_splice_read(struct file *in, struct pipe_inode_info *pipe, | |||
| 241 | pgoff_t index; | 242 | pgoff_t index; |
| 242 | int i, error; | 243 | int i, error; |
| 243 | 244 | ||
| 244 | index = in->f_pos >> PAGE_CACHE_SHIFT; | 245 | index = *ppos >> PAGE_CACHE_SHIFT; |
| 245 | offset = in->f_pos & ~PAGE_CACHE_MASK; | 246 | offset = *ppos & ~PAGE_CACHE_MASK; |
| 246 | nr_pages = (len + offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | 247 | nr_pages = (len + offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; |
| 247 | 248 | ||
| 248 | if (nr_pages > PIPE_BUFFERS) | 249 | if (nr_pages > PIPE_BUFFERS) |
| @@ -348,8 +349,9 @@ fill_it: | |||
| 348 | * | 349 | * |
| 349 | * Will read pages from given file and fill them into a pipe. | 350 | * Will read pages from given file and fill them into a pipe. |
| 350 | */ | 351 | */ |
| 351 | ssize_t generic_file_splice_read(struct file *in, struct pipe_inode_info *pipe, | 352 | ssize_t generic_file_splice_read(struct file *in, loff_t *ppos, |
| 352 | size_t len, unsigned int flags) | 353 | struct pipe_inode_info *pipe, size_t len, |
| 354 | unsigned int flags) | ||
| 353 | { | 355 | { |
| 354 | ssize_t spliced; | 356 | ssize_t spliced; |
| 355 | int ret; | 357 | int ret; |
| @@ -358,12 +360,12 @@ ssize_t generic_file_splice_read(struct file *in, struct pipe_inode_info *pipe, | |||
| 358 | spliced = 0; | 360 | spliced = 0; |
| 359 | 361 | ||
| 360 | while (len) { | 362 | while (len) { |
| 361 | ret = __generic_file_splice_read(in, pipe, len, flags); | 363 | ret = __generic_file_splice_read(in, ppos, pipe, len, flags); |
| 362 | 364 | ||
| 363 | if (ret <= 0) | 365 | if (ret <= 0) |
| 364 | break; | 366 | break; |
| 365 | 367 | ||
| 366 | in->f_pos += ret; | 368 | *ppos += ret; |
| 367 | len -= ret; | 369 | len -= ret; |
| 368 | spliced += ret; | 370 | spliced += ret; |
| 369 | 371 | ||
| @@ -561,7 +563,7 @@ typedef int (splice_actor)(struct pipe_inode_info *, struct pipe_buffer *, | |||
| 561 | * to the wanted destination. See pipe_to_file/pipe_to_sendpage above. | 563 | * to the wanted destination. See pipe_to_file/pipe_to_sendpage above. |
| 562 | */ | 564 | */ |
| 563 | static ssize_t move_from_pipe(struct pipe_inode_info *pipe, struct file *out, | 565 | static ssize_t move_from_pipe(struct pipe_inode_info *pipe, struct file *out, |
| 564 | size_t len, unsigned int flags, | 566 | loff_t *ppos, size_t len, unsigned int flags, |
| 565 | splice_actor *actor) | 567 | splice_actor *actor) |
| 566 | { | 568 | { |
| 567 | int ret, do_wakeup, err; | 569 | int ret, do_wakeup, err; |
| @@ -573,7 +575,7 @@ static ssize_t move_from_pipe(struct pipe_inode_info *pipe, struct file *out, | |||
| 573 | sd.total_len = len; | 575 | sd.total_len = len; |
| 574 | sd.flags = flags; | 576 | sd.flags = flags; |
| 575 | sd.file = out; | 577 | sd.file = out; |
| 576 | sd.pos = out->f_pos; | 578 | sd.pos = *ppos; |
| 577 | 579 | ||
| 578 | if (pipe->inode) | 580 | if (pipe->inode) |
| 579 | mutex_lock(&pipe->inode->i_mutex); | 581 | mutex_lock(&pipe->inode->i_mutex); |
| @@ -656,9 +658,7 @@ static ssize_t move_from_pipe(struct pipe_inode_info *pipe, struct file *out, | |||
| 656 | kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT); | 658 | kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT); |
| 657 | } | 659 | } |
| 658 | 660 | ||
| 659 | out->f_pos = sd.pos; | ||
| 660 | return ret; | 661 | return ret; |
| 661 | |||
| 662 | } | 662 | } |
| 663 | 663 | ||
| 664 | /** | 664 | /** |
| @@ -674,12 +674,12 @@ static ssize_t move_from_pipe(struct pipe_inode_info *pipe, struct file *out, | |||
| 674 | */ | 674 | */ |
| 675 | ssize_t | 675 | ssize_t |
| 676 | generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, | 676 | generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, |
| 677 | size_t len, unsigned int flags) | 677 | loff_t *ppos, size_t len, unsigned int flags) |
| 678 | { | 678 | { |
| 679 | struct address_space *mapping = out->f_mapping; | 679 | struct address_space *mapping = out->f_mapping; |
| 680 | ssize_t ret; | 680 | ssize_t ret; |
| 681 | 681 | ||
| 682 | ret = move_from_pipe(pipe, out, len, flags, pipe_to_file); | 682 | ret = move_from_pipe(pipe, out, ppos, len, flags, pipe_to_file); |
| 683 | 683 | ||
| 684 | /* | 684 | /* |
| 685 | * If file or inode is SYNC and we actually wrote some data, sync it. | 685 | * If file or inode is SYNC and we actually wrote some data, sync it. |
| @@ -715,9 +715,9 @@ EXPORT_SYMBOL(generic_file_splice_write); | |||
| 715 | * | 715 | * |
| 716 | */ | 716 | */ |
| 717 | ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe, struct file *out, | 717 | ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe, struct file *out, |
| 718 | size_t len, unsigned int flags) | 718 | loff_t *ppos, size_t len, unsigned int flags) |
| 719 | { | 719 | { |
| 720 | return move_from_pipe(pipe, out, len, flags, pipe_to_sendpage); | 720 | return move_from_pipe(pipe, out, ppos, len, flags, pipe_to_sendpage); |
| 721 | } | 721 | } |
| 722 | 722 | ||
| 723 | EXPORT_SYMBOL(generic_splice_sendpage); | 723 | EXPORT_SYMBOL(generic_splice_sendpage); |
| @@ -726,9 +726,8 @@ EXPORT_SYMBOL(generic_splice_sendpage); | |||
| 726 | * Attempt to initiate a splice from pipe to file. | 726 | * Attempt to initiate a splice from pipe to file. |
| 727 | */ | 727 | */ |
| 728 | static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, | 728 | static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, |
| 729 | size_t len, unsigned int flags) | 729 | loff_t *ppos, size_t len, unsigned int flags) |
| 730 | { | 730 | { |
| 731 | loff_t pos; | ||
| 732 | int ret; | 731 | int ret; |
| 733 | 732 | ||
| 734 | if (unlikely(!out->f_op || !out->f_op->splice_write)) | 733 | if (unlikely(!out->f_op || !out->f_op->splice_write)) |
| @@ -737,22 +736,21 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, | |||
| 737 | if (unlikely(!(out->f_mode & FMODE_WRITE))) | 736 | if (unlikely(!(out->f_mode & FMODE_WRITE))) |
| 738 | return -EBADF; | 737 | return -EBADF; |
| 739 | 738 | ||
| 740 | pos = out->f_pos; | 739 | ret = rw_verify_area(WRITE, out, ppos, len); |
| 741 | |||
| 742 | ret = rw_verify_area(WRITE, out, &pos, len); | ||
| 743 | if (unlikely(ret < 0)) | 740 | if (unlikely(ret < 0)) |
| 744 | return ret; | 741 | return ret; |
| 745 | 742 | ||
| 746 | return out->f_op->splice_write(pipe, out, len, flags); | 743 | return out->f_op->splice_write(pipe, out, ppos, len, flags); |
| 747 | } | 744 | } |
| 748 | 745 | ||
| 749 | /* | 746 | /* |
| 750 | * Attempt to initiate a splice from a file to a pipe. | 747 | * Attempt to initiate a splice from a file to a pipe. |
| 751 | */ | 748 | */ |
| 752 | static long do_splice_to(struct file *in, struct pipe_inode_info *pipe, | 749 | static long do_splice_to(struct file *in, loff_t *ppos, |
| 753 | size_t len, unsigned int flags) | 750 | struct pipe_inode_info *pipe, size_t len, |
| 751 | unsigned int flags) | ||
| 754 | { | 752 | { |
| 755 | loff_t pos, isize, left; | 753 | loff_t isize, left; |
| 756 | int ret; | 754 | int ret; |
| 757 | 755 | ||
| 758 | if (unlikely(!in->f_op || !in->f_op->splice_read)) | 756 | if (unlikely(!in->f_op || !in->f_op->splice_read)) |
| @@ -761,28 +759,27 @@ static long do_splice_to(struct file *in, struct pipe_inode_info *pipe, | |||
| 761 | if (unlikely(!(in->f_mode & FMODE_READ))) | 759 | if (unlikely(!(in->f_mode & FMODE_READ))) |
| 762 | return -EBADF; | 760 | return -EBADF; |
| 763 | 761 | ||
| 764 | pos = in->f_pos; | 762 | ret = rw_verify_area(READ, in, ppos, len); |
| 765 | |||
| 766 | ret = rw_verify_area(READ, in, &pos, len); | ||
| 767 | if (unlikely(ret < 0)) | 763 | if (unlikely(ret < 0)) |
| 768 | return ret; | 764 | return ret; |
| 769 | 765 | ||
| 770 | isize = i_size_read(in->f_mapping->host); | 766 | isize = i_size_read(in->f_mapping->host); |
| 771 | if (unlikely(in->f_pos >= isize)) | 767 | if (unlikely(*ppos >= isize)) |
| 772 | return 0; | 768 | return 0; |
| 773 | 769 | ||
| 774 | left = isize - in->f_pos; | 770 | left = isize - *ppos; |
| 775 | if (unlikely(left < len)) | 771 | if (unlikely(left < len)) |
| 776 | len = left; | 772 | len = left; |
| 777 | 773 | ||
| 778 | return in->f_op->splice_read(in, pipe, len, flags); | 774 | return in->f_op->splice_read(in, ppos, pipe, len, flags); |
| 779 | } | 775 | } |
| 780 | 776 | ||
| 781 | long do_splice_direct(struct file *in, struct file *out, size_t len, | 777 | long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, |
| 782 | unsigned int flags) | 778 | size_t len, unsigned int flags) |
| 783 | { | 779 | { |
| 784 | struct pipe_inode_info *pipe; | 780 | struct pipe_inode_info *pipe; |
| 785 | long ret, bytes; | 781 | long ret, bytes; |
| 782 | loff_t out_off; | ||
| 786 | umode_t i_mode; | 783 | umode_t i_mode; |
| 787 | int i; | 784 | int i; |
| 788 | 785 | ||
| @@ -820,6 +817,7 @@ long do_splice_direct(struct file *in, struct file *out, size_t len, | |||
