aboutsummaryrefslogtreecommitdiffstats
path: root/fs/splice.c
diff options
context:
space:
mode:
authorJens Axboe <axboe@suse.de>2006-04-11 08:57:50 -0400
committerJens Axboe <axboe@nelson.home.kernel.dk>2006-04-11 09:47:07 -0400
commitcbb7e577e732f576b9f399bc2600bdc0626c68dc (patch)
tree55e3d65c9d9fb5b0ee25d0ccabf951de6da2db7b /fs/splice.c
parent2514395ef88b46e895726a8d40966cb83de7940c (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>
Diffstat (limited to 'fs/splice.c')
-rw-r--r--fs/splice.c86
1 files changed, 44 insertions, 42 deletions
diff --git a/fs/splice.c b/fs/splice.c
index e50a460239dd..5d3eda64703b 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
233static int 233static 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 */
351ssize_t generic_file_splice_read(struct file *in, struct pipe_inode_info *pipe, 352ssize_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 */
563static ssize_t move_from_pipe(struct pipe_inode_info *pipe, struct file *out, 565static 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 */
675ssize_t 675ssize_t
676generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, 676generic_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 */
717ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe, struct file *out, 717ssize_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
723EXPORT_SYMBOL(generic_splice_sendpage); 723EXPORT_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 */
728static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, 728static 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 */
752static long do_splice_to(struct file *in, struct pipe_inode_info *pipe, 749static 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
781long do_splice_direct(struct file *in, struct file *out, size_t len, 777long 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,
820 */ 817 */
821 ret = 0; 818 ret = 0;
822 bytes = 0; 819 bytes = 0;
820 out_off = 0;
823 821
824 while (len) { 822 while (len) {
825 size_t read_len, max_read_len; 823 size_t read_len, max_read_len;
@@ -829,7 +827,7 @@ long do_splice_direct(struct file *in, struct file *out, size_t len,
829 */ 827 */
830 max_read_len = min(len, (size_t)(PIPE_BUFFERS*PAGE_SIZE)); 828 max_read_len = min(len, (size_t)(PIPE_BUFFERS*PAGE_SIZE));
831 829
832 ret = do_splice_to(in, pipe, max_read_len, flags); 830 ret = do_splice_to(in, ppos, pipe, max_read_len, flags);
833 if (unlikely(ret < 0)) 831 if (unlikely(ret < 0))
834 goto out_release; 832 goto out_release;
835 833
@@ -840,7 +838,7 @@ long do_splice_direct(struct file *in, struct file *out, size_t len,
840 * must not do the output in nonblocking mode as then we 838 * must not do the output in nonblocking mode as then we
841 * could get stuck data in the internal pipe: 839 * could get stuck data in the internal pipe:
842 */ 840 */
843 ret = do_splice_from(pipe, out, read_len, 841 ret = do_splice_from(pipe, out, &out_off, read_len,
844 flags & ~SPLICE_F_NONBLOCK); 842 flags & ~SPLICE_F_NONBLOCK);
845 if (unlikely(ret < 0)) 843 if (unlikely(ret < 0))
846 goto out_release; 844 goto out_release;
@@ -898,6 +896,7 @@ static long do_splice(struct file *in, loff_t __user *off_in,
898 size_t len, unsigned int flags) 896 size_t len, unsigned int flags)
899{ 897{
900 struct pipe_inode_info *pipe; 898 struct pipe_inode_info *pipe;
899 loff_t offset, *off;
901 900
902 pipe = in->f_dentry->d_inode->i_pipe; 901 pipe = in->f_dentry->d_inode->i_pipe;
903 if (pipe) { 902 if (pipe) {
@@ -906,12 +905,13 @@ static long do_splice(struct file *in, loff_t __user *off_in,
906 if (off_out) { 905 if (off_out) {
907 if (out->f_op->llseek == no_llseek) 906 if (out->f_op->llseek == no_llseek)
908 return -EINVAL; 907 return -EINVAL;
909 if (copy_from_user(&out->f_pos, off_out, 908 if (copy_from_user(&offset, off_out, sizeof(loff_t)))
910 sizeof(loff_t)))
911 return -EFAULT; 909 return -EFAULT;
912 } 910 off = &offset;
911 } else
912 off = &out->f_pos;
913 913
914 return do_splice_from(pipe, out, len, flags); 914 return do_splice_from(pipe, out, off, len, flags);
915 } 915 }
916 916
917 pipe = out->f_dentry->d_inode->i_pipe; 917 pipe = out->f_dentry->d_inode->i_pipe;
@@ -921,11 +921,13 @@ static long do_splice(struct file *in, loff_t __user *off_in,
921 if (off_in) { 921 if (off_in) {
922 if (in->f_op->llseek == no_llseek) 922 if (in->f_op->llseek == no_llseek)
923 return -EINVAL; 923 return -EINVAL;
924 if (copy_from_user(&in->f_pos, off_in, sizeof(loff_t))) 924 if (copy_from_user(&offset, off_in, sizeof(loff_t)))
925 return -EFAULT; 925 return -EFAULT;
926 } 926 off = &offset;
927 } else
928 off = &in->f_pos;
927 929
928 return do_splice_to(in, pipe, len, flags); 930 return do_splice_to(in, off, pipe, len, flags);
929 } 931 }
930 932
931 return -EINVAL; 933 return -EINVAL;