[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>
This commit is contained in:
Jens Axboe 2006-04-19 15:57:05 +02:00
parent 2a27250e6c
commit a4514ebd8e

View File

@ -720,22 +720,26 @@ 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) {
/*
* 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) {
struct inode *inode = mapping->host; struct inode *inode = mapping->host;
int err;
mutex_lock(&inode->i_mutex); *ppos += ret;
err = generic_osync_inode(mapping->host, mapping,
OSYNC_METADATA|OSYNC_DATA);
mutex_unlock(&inode->i_mutex);
if (err) /*
ret = err; * 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;
}
} }
return ret; return ret;
@ -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,
} 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,
} 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;