Commit 7995bd28 authored by Al Viro's avatar Al Viro

splice: don't pass the address of ->f_pos to methods

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent c9036e9f
...@@ -131,6 +131,12 @@ extern struct dentry *__d_alloc(struct super_block *, const struct qstr *); ...@@ -131,6 +131,12 @@ extern struct dentry *__d_alloc(struct super_block *, const struct qstr *);
*/ */
extern ssize_t __kernel_write(struct file *, const char *, size_t, loff_t *); extern ssize_t __kernel_write(struct file *, const char *, size_t, loff_t *);
/*
* splice.c
*/
extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
loff_t *opos, size_t len, unsigned int flags);
/* /*
* pipe.c * pipe.c
*/ */
......
...@@ -1064,6 +1064,7 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, ...@@ -1064,6 +1064,7 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
struct fd in, out; struct fd in, out;
struct inode *in_inode, *out_inode; struct inode *in_inode, *out_inode;
loff_t pos; loff_t pos;
loff_t out_pos;
ssize_t retval; ssize_t retval;
int fl; int fl;
...@@ -1077,12 +1078,14 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, ...@@ -1077,12 +1078,14 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
if (!(in.file->f_mode & FMODE_READ)) if (!(in.file->f_mode & FMODE_READ))
goto fput_in; goto fput_in;
retval = -ESPIPE; retval = -ESPIPE;
if (!ppos) if (!ppos) {
ppos = &in.file->f_pos; pos = in.file->f_pos;
else } else {
pos = *ppos;
if (!(in.file->f_mode & FMODE_PREAD)) if (!(in.file->f_mode & FMODE_PREAD))
goto fput_in; goto fput_in;
retval = rw_verify_area(READ, in.file, ppos, count); }
retval = rw_verify_area(READ, in.file, &pos, count);
if (retval < 0) if (retval < 0)
goto fput_in; goto fput_in;
count = retval; count = retval;
...@@ -1099,7 +1102,8 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, ...@@ -1099,7 +1102,8 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
retval = -EINVAL; retval = -EINVAL;
in_inode = file_inode(in.file); in_inode = file_inode(in.file);
out_inode = file_inode(out.file); out_inode = file_inode(out.file);
retval = rw_verify_area(WRITE, out.file, &out.file->f_pos, count); out_pos = out.file->f_pos;
retval = rw_verify_area(WRITE, out.file, &out_pos, count);
if (retval < 0) if (retval < 0)
goto fput_out; goto fput_out;
count = retval; count = retval;
...@@ -1107,7 +1111,6 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, ...@@ -1107,7 +1111,6 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
if (!max) if (!max)
max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes); max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes);
pos = *ppos;
if (unlikely(pos + count > max)) { if (unlikely(pos + count > max)) {
retval = -EOVERFLOW; retval = -EOVERFLOW;
if (pos >= max) if (pos >= max)
...@@ -1126,18 +1129,23 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, ...@@ -1126,18 +1129,23 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
if (in.file->f_flags & O_NONBLOCK) if (in.file->f_flags & O_NONBLOCK)
fl = SPLICE_F_NONBLOCK; fl = SPLICE_F_NONBLOCK;
#endif #endif
retval = do_splice_direct(in.file, ppos, out.file, count, fl); retval = do_splice_direct(in.file, &pos, out.file, &out_pos, count, fl);
if (retval > 0) { if (retval > 0) {
add_rchar(current, retval); add_rchar(current, retval);
add_wchar(current, retval); add_wchar(current, retval);
fsnotify_access(in.file); fsnotify_access(in.file);
fsnotify_modify(out.file); fsnotify_modify(out.file);
out.file->f_pos = out_pos;
if (ppos)
*ppos = pos;
else
in.file->f_pos = pos;
} }
inc_syscr(current); inc_syscr(current);
inc_syscw(current); inc_syscw(current);
if (*ppos > max) if (pos > max)
retval = -EOVERFLOW; retval = -EOVERFLOW;
fput_out: fput_out:
......
...@@ -1274,7 +1274,7 @@ static int direct_splice_actor(struct pipe_inode_info *pipe, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 {
} else offset = out->f_pos;
off = &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, ...@@ -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 {
} else offset = in->f_pos;
off = &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;
......
...@@ -2414,8 +2414,6 @@ extern ssize_t generic_file_splice_write(struct pipe_inode_info *, ...@@ -2414,8 +2414,6 @@ extern ssize_t generic_file_splice_write(struct pipe_inode_info *,
struct file *, loff_t *, size_t, unsigned int); struct file *, loff_t *, size_t, unsigned int);
extern ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe, extern ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe,
struct file *out, loff_t *, size_t len, unsigned int flags); struct file *out, loff_t *, size_t len, unsigned int flags);
extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
size_t len, unsigned int flags);
extern void extern void
file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping); file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping);
......
...@@ -35,6 +35,7 @@ struct splice_desc { ...@@ -35,6 +35,7 @@ struct splice_desc {
void *data; /* cookie */ void *data; /* cookie */
} u; } u;
loff_t pos; /* file position */ loff_t pos; /* file position */
loff_t *opos; /* sendfile: output position */
size_t num_spliced; /* number of bytes already spliced */ size_t num_spliced; /* number of bytes already spliced */
bool need_wakeup; /* need to wake up writer */ bool need_wakeup; /* need to wake up writer */
}; };
......
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