summaryrefslogtreecommitdiff
path: root/fs/splice.c
diff options
context:
space:
mode:
authorJens Axboe <axboe@suse.de>2006-04-19 15:57:05 +0200
committerJens Axboe <axboe@suse.de>2006-04-19 15:57:05 +0200
commita4514ebd8e12c63c09ab02be518db545bd1d24af (patch)
treeec7bcaed8d4594bd9d763659686e9318158da3aa /fs/splice.c
parent2a27250e6cf47ca1ea3bea0a55e4b7889c097627 (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>
Diffstat (limited to 'fs/splice.c')
-rw-r--r--fs/splice.c45
1 files changed, 30 insertions, 15 deletions
diff --git a/fs/splice.c b/fs/splice.c
index 4f5e6b09fb2..27d6408ff49 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,
ssize_t ret;
ret = move_from_pipe(pipe, out, ppos, len, flags, pipe_to_file);
-
- /*
- * If file or inode is SYNC and we actually wrote some data, sync it.
- */
- if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(mapping->host))
- && ret > 0) {
+ if (ret > 0) {
struct inode *inode = mapping->host;
- int err;
- mutex_lock(&inode->i_mutex);
- err = generic_osync_inode(mapping->host, mapping,
- OSYNC_METADATA|OSYNC_DATA);
- mutex_unlock(&inode->i_mutex);
+ *ppos += ret;
+
+ /*
+ * If file or inode is SYNC and we actually wrote some data,
+ * sync it.
+ */
+ if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) {
+ int err;
+
+ mutex_lock(&inode->i_mutex);
+ err = generic_osync_inode(inode, mapping,
+ OSYNC_METADATA|OSYNC_DATA);
+ mutex_unlock(&inode->i_mutex);
- if (err)
- ret = err;
+ if (err)
+ ret = err;
+ }
}
return ret;
@@ -937,6 +941,7 @@ static long do_splice(struct file *in, loff_t __user *off_in,
{
struct pipe_inode_info *pipe;
loff_t offset, *off;
+ long ret;
pipe = in->f_dentry->d_inode->i_pipe;
if (pipe) {
@@ -951,7 +956,12 @@ static long do_splice(struct file *in, loff_t __user *off_in,
} else
off = &out->f_pos;
- return do_splice_from(pipe, out, off, len, flags);
+ ret = do_splice_from(pipe, out, off, len, flags);
+
+ if (off_out && copy_to_user(off_out, off, sizeof(loff_t)))
+ ret = -EFAULT;
+
+ return ret;
}
pipe = out->f_dentry->d_inode->i_pipe;
@@ -967,7 +977,12 @@ static long do_splice(struct file *in, loff_t __user *off_in,
} else
off = &in->f_pos;
- return do_splice_to(in, off, pipe, len, flags);
+ ret = do_splice_to(in, off, pipe, len, flags);
+
+ if (off_in && copy_to_user(off_in, off, sizeof(loff_t)))
+ ret = -EFAULT;
+
+ return ret;
}
return -EINVAL;