Commit a4514ebd authored by Jens Axboe's avatar Jens Axboe

[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: default avatarJens Axboe <axboe@suse.de>
parent 2a27250e
...@@ -720,23 +720,27 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, ...@@ -720,23 +720,27 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
ssize_t ret; ssize_t ret;
ret = move_from_pipe(pipe, out, ppos, len, flags, pipe_to_file); ret = move_from_pipe(pipe, out, ppos, len, flags, pipe_to_file);
if (ret > 0) {
struct inode *inode = mapping->host;
*ppos += ret;
/* /*
* If file or inode is SYNC and we actually wrote some data, sync it. * 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)) if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) {
&& ret > 0) {
struct inode *inode = mapping->host;
int err; int err;
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
err = generic_osync_inode(mapping->host, mapping, err = generic_osync_inode(inode, mapping,
OSYNC_METADATA|OSYNC_DATA); OSYNC_METADATA|OSYNC_DATA);
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
if (err) if (err)
ret = err; ret = err;
} }
}
return ret; return ret;
} }
...@@ -937,6 +941,7 @@ static long do_splice(struct file *in, loff_t __user *off_in, ...@@ -937,6 +941,7 @@ static long do_splice(struct file *in, loff_t __user *off_in,
{ {
struct pipe_inode_info *pipe; struct pipe_inode_info *pipe;
loff_t offset, *off; loff_t offset, *off;
long ret;
pipe = in->f_dentry->d_inode->i_pipe; pipe = in->f_dentry->d_inode->i_pipe;
if (pipe) { if (pipe) {
...@@ -951,7 +956,12 @@ static long do_splice(struct file *in, loff_t __user *off_in, ...@@ -951,7 +956,12 @@ static long do_splice(struct file *in, loff_t __user *off_in,
} else } else
off = &out->f_pos; 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; 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,7 +977,12 @@ static long do_splice(struct file *in, loff_t __user *off_in,
} else } else
off = &in->f_pos; 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; return -EINVAL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment