|
@@ -1274,7 +1274,7 @@ static int direct_splice_actor(struct pipe_inode_info *pipe,
|
|
{
|
|
{
|
|
struct file *file = sd->u.file;
|
|
struct file *file = sd->u.file;
|
|
|
|
|
|
- return do_splice_from(pipe, file, &file->f_pos, sd->total_len,
|
|
|
|
|
|
+ return do_splice_from(pipe, file, sd->opos, sd->total_len,
|
|
sd->flags);
|
|
sd->flags);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1294,7 +1294,7 @@ static int direct_splice_actor(struct pipe_inode_info *pipe,
|
|
*
|
|
*
|
|
*/
|
|
*/
|
|
long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
|
|
long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
|
|
- size_t len, unsigned int flags)
|
|
|
|
|
|
+ loff_t *opos, size_t len, unsigned int flags)
|
|
{
|
|
{
|
|
struct splice_desc sd = {
|
|
struct splice_desc sd = {
|
|
.len = len,
|
|
.len = len,
|
|
@@ -1302,6 +1302,7 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
|
|
.flags = flags,
|
|
.flags = flags,
|
|
.pos = *ppos,
|
|
.pos = *ppos,
|
|
.u.file = out,
|
|
.u.file = out,
|
|
|
|
+ .opos = opos,
|
|
};
|
|
};
|
|
long ret;
|
|
long ret;
|
|
|
|
|
|
@@ -1325,7 +1326,7 @@ static long do_splice(struct file *in, loff_t __user *off_in,
|
|
{
|
|
{
|
|
struct pipe_inode_info *ipipe;
|
|
struct pipe_inode_info *ipipe;
|
|
struct pipe_inode_info *opipe;
|
|
struct pipe_inode_info *opipe;
|
|
- loff_t offset, *off;
|
|
|
|
|
|
+ loff_t offset;
|
|
long ret;
|
|
long ret;
|
|
|
|
|
|
ipipe = get_pipe_info(in);
|
|
ipipe = get_pipe_info(in);
|
|
@@ -1356,13 +1357,15 @@ static long do_splice(struct file *in, loff_t __user *off_in,
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
if (copy_from_user(&offset, off_out, sizeof(loff_t)))
|
|
if (copy_from_user(&offset, off_out, sizeof(loff_t)))
|
|
return -EFAULT;
|
|
return -EFAULT;
|
|
- off = &offset;
|
|
|
|
- } else
|
|
|
|
- off = &out->f_pos;
|
|
|
|
|
|
+ } else {
|
|
|
|
+ offset = out->f_pos;
|
|
|
|
+ }
|
|
|
|
|
|
- ret = do_splice_from(ipipe, out, off, len, flags);
|
|
|
|
|
|
+ ret = do_splice_from(ipipe, out, &offset, len, flags);
|
|
|
|
|
|
- if (off_out && copy_to_user(off_out, off, sizeof(loff_t)))
|
|
|
|
|
|
+ if (!off_out)
|
|
|
|
+ out->f_pos = offset;
|
|
|
|
+ else if (copy_to_user(off_out, &offset, sizeof(loff_t)))
|
|
ret = -EFAULT;
|
|
ret = -EFAULT;
|
|
|
|
|
|
return ret;
|
|
return ret;
|
|
@@ -1376,13 +1379,15 @@ static long do_splice(struct file *in, loff_t __user *off_in,
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
if (copy_from_user(&offset, off_in, sizeof(loff_t)))
|
|
if (copy_from_user(&offset, off_in, sizeof(loff_t)))
|
|
return -EFAULT;
|
|
return -EFAULT;
|
|
- off = &offset;
|
|
|
|
- } else
|
|
|
|
- off = &in->f_pos;
|
|
|
|
|
|
+ } else {
|
|
|
|
+ offset = in->f_pos;
|
|
|
|
+ }
|
|
|
|
|
|
- ret = do_splice_to(in, off, opipe, len, flags);
|
|
|
|
|
|
+ ret = do_splice_to(in, &offset, opipe, len, flags);
|
|
|
|
|
|
- if (off_in && copy_to_user(off_in, off, sizeof(loff_t)))
|
|
|
|
|
|
+ if (!off_in)
|
|
|
|
+ in->f_pos = offset;
|
|
|
|
+ else if (copy_to_user(off_in, &offset, sizeof(loff_t)))
|
|
ret = -EFAULT;
|
|
ret = -EFAULT;
|
|
|
|
|
|
return ret;
|
|
return ret;
|