diff options
author | Jens Axboe <axboe@suse.de> | 2006-04-19 09:57:05 -0400 |
---|---|---|
committer | Jens Axboe <axboe@suse.de> | 2006-04-19 09:57:05 -0400 |
commit | a4514ebd8e12c63c09ab02be518db545bd1d24af (patch) | |
tree | ec7bcaed8d4594bd9d763659686e9318158da3aa | |
parent | 2a27250e6cf47ca1ea3bea0a55e4b7889c097627 (diff) |
[PATCH] splice: offset fixes
- We need to adjust *ppos for writes as well.
- Copy back modified offset value if one was passed in, similar to
what sendfile does.
Signed-off-by: Jens Axboe <axboe@suse.de>
-rw-r--r-- | fs/splice.c | 45 |
1 files changed, 30 insertions, 15 deletions
diff --git a/fs/splice.c b/fs/splice.c index 4f5e6b09fb26..27d6408ff490 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
@@ -720,22 +720,26 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, | |||
720 | ssize_t ret; | 720 | ssize_t ret; |
721 | 721 | ||
722 | ret = move_from_pipe(pipe, out, ppos, len, flags, pipe_to_file); | 722 | ret = move_from_pipe(pipe, out, ppos, len, flags, pipe_to_file); |
723 | 723 | if (ret > 0) { | |
724 | /* | ||
725 | * If file or inode is SYNC and we actually wrote some data, sync it. | ||
726 | */ | ||
727 | if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(mapping->host)) | ||
728 | && ret > 0) { | ||
729 | struct inode *inode = mapping->host; | 724 | struct inode *inode = mapping->host; |
730 | int err; | ||
731 | 725 | ||
732 | mutex_lock(&inode->i_mutex); | 726 | *ppos += ret; |
733 | err = generic_osync_inode(mapping->host, mapping, | 727 | |
734 | OSYNC_METADATA|OSYNC_DATA); | 728 | /* |
735 | mutex_unlock(&inode->i_mutex); | 729 | * If file or inode is SYNC and we actually wrote some data, |
730 | * sync it. | ||
731 | */ | ||
732 | if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) { | ||
733 | int err; | ||
734 | |||
735 | mutex_lock(&inode->i_mutex); | ||
736 | err = generic_osync_inode(inode, mapping, | ||
737 | OSYNC_METADATA|OSYNC_DATA); | ||
738 | mutex_unlock(&inode->i_mutex); | ||
736 | 739 | ||
737 | if (err) | 740 | if (err) |
738 | ret = err; | 741 | ret = err; |
742 | } | ||
739 | } | 743 | } |
740 | 744 | ||
741 | return ret; | 745 | return ret; |
@@ -937,6 +941,7 @@ static long do_splice(struct file *in, loff_t __user *off_in, | |||
937 | { | 941 | { |
938 | struct pipe_inode_info *pipe; | 942 | struct pipe_inode_info *pipe; |
939 | loff_t offset, *off; | 943 | loff_t offset, *off; |
944 | long ret; | ||
940 | 945 | ||
941 | pipe = in->f_dentry->d_inode->i_pipe; | 946 | pipe = in->f_dentry->d_inode->i_pipe; |
942 | if (pipe) { | 947 | if (pipe) { |
@@ -951,7 +956,12 @@ static long do_splice(struct file *in, loff_t __user *off_in, | |||
951 | } else | 956 | } else |
952 | off = &out->f_pos; | 957 | off = &out->f_pos; |
953 | 958 | ||
954 | return do_splice_from(pipe, out, off, len, flags); | 959 | ret = do_splice_from(pipe, out, off, len, flags); |
960 | |||
961 | if (off_out && copy_to_user(off_out, off, sizeof(loff_t))) | ||
962 | ret = -EFAULT; | ||
963 | |||
964 | return ret; | ||
955 | } | 965 | } |
956 | 966 | ||
957 | pipe = out->f_dentry->d_inode->i_pipe; | 967 | pipe = out->f_dentry->d_inode->i_pipe; |
@@ -967,7 +977,12 @@ static long do_splice(struct file *in, loff_t __user *off_in, | |||
967 | } else | 977 | } else |
968 | off = &in->f_pos; | 978 | off = &in->f_pos; |
969 | 979 | ||
970 | return do_splice_to(in, off, pipe, len, flags); | 980 | ret = do_splice_to(in, off, pipe, len, flags); |
981 | |||
982 | if (off_in && copy_to_user(off_in, off, sizeof(loff_t))) | ||
983 | ret = -EFAULT; | ||
984 | |||
985 | return ret; | ||
971 | } | 986 | } |
972 | 987 | ||
973 | return -EINVAL; | 988 | return -EINVAL; |