From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-eopbgr10092.outbound.protection.outlook.com ([40.107.1.92]:64992 "EHLO EUR02-HE1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S934240AbeFGR4e (ORCPT ); Thu, 7 Jun 2018 13:56:34 -0400 Date: Thu, 7 Jun 2018 10:56:23 -0700 From: Andrei Vagin To: Al Viro Cc: linux-fsdevel@vger.kernel.org Subject: Re: [1/4] vmsplice: lift import_iovec() into do_vmsplice() Message-ID: <20180607175622.GA12359@outlook.office365.com> References: <20180528222013.18402-1-viro@ZenIV.linux.org.uk> <20180606225751.GA1261@outlook.office365.com> MIME-Version: 1.0 Content-Type: text/plain; charset=koi8-r Content-Disposition: inline In-Reply-To: <20180606225751.GA1261@outlook.office365.com> Sender: linux-fsdevel-owner@vger.kernel.org List-ID: On Wed, Jun 06, 2018 at 03:57:51PM -0700, Andrei Vagin wrote: > On Mon, May 28, 2018 at 11:20:10PM +0100, Al Viro wrote: > > From: Al Viro > > > > Signed-off-by: Al Viro > > --- > > fs/splice.c | 69 ++++++++++++++++++++++++++----------------------------------- > > 1 file changed, 29 insertions(+), 40 deletions(-) > > > > diff --git a/fs/splice.c b/fs/splice.c > > index 005d09cf3fa8..920ff0b20e53 100644 > > --- a/fs/splice.c > > +++ b/fs/splice.c > > @@ -1242,38 +1242,26 @@ static int pipe_to_user(struct pipe_inode_info *pipe, struct pipe_buffer *buf, > > * For lack of a better implementation, implement vmsplice() to userspace > > * as a simple copy of the pipes pages to the user iov. > > */ > > -static long vmsplice_to_user(struct file *file, const struct iovec __user *uiov, > > - unsigned long nr_segs, unsigned int flags) > > +static long vmsplice_to_user(struct file *file, struct iov_iter *iter, > > + unsigned int flags) > > { > > - struct pipe_inode_info *pipe; > > - struct splice_desc sd; > > - long ret; > > - struct iovec iovstack[UIO_FASTIOV]; > > - struct iovec *iov = iovstack; > > - struct iov_iter iter; > > + struct pipe_inode_info *pipe = get_pipe_info(file); > > + struct splice_desc sd = { > > + .total_len = iov_iter_count(iter), > > + .flags = flags, > > + .u.data = iter > > + }; > > + long ret = 0; > > > > - pipe = get_pipe_info(file); > > if (!pipe) > > return -EBADF; > > > > - ret = import_iovec(READ, uiov, nr_segs, > > - ARRAY_SIZE(iovstack), &iov, &iter); > > - if (ret < 0) > > - return ret; > > - > > - sd.total_len = iov_iter_count(&iter); > > - sd.len = 0; > > - sd.flags = flags; > > - sd.u.data = &iter; > > - sd.pos = 0; > > - > > if (sd.total_len) { > > pipe_lock(pipe); > > ret = __splice_from_pipe(pipe, &sd, pipe_to_user); > > pipe_unlock(pipe); > > } > > > > - kfree(iov); > > return ret; > > } > > > > @@ -1282,14 +1270,11 @@ static long vmsplice_to_user(struct file *file, const struct iovec __user *uiov, > > * as splice-from-memory, where the regular splice is splice-from-file (or > > * to file). In both cases the output is a pipe, naturally. > > */ > > -static long vmsplice_to_pipe(struct file *file, const struct iovec __user *uiov, > > - unsigned long nr_segs, unsigned int flags) > > +static long vmsplice_to_pipe(struct file *file, struct iov_iter *iter, > > + unsigned int flags) > > { > > struct pipe_inode_info *pipe; > > - struct iovec iovstack[UIO_FASTIOV]; > > - struct iovec *iov = iovstack; > > - struct iov_iter from; > > - long ret; > > + long ret = 0; > > unsigned buf_flag = 0; > > > > if (flags & SPLICE_F_GIFT) > > @@ -1299,19 +1284,13 @@ static long vmsplice_to_pipe(struct file *file, const struct iovec __user *uiov, > > if (!pipe) > > return -EBADF; > > > > - ret = import_iovec(WRITE, uiov, nr_segs, > > - ARRAY_SIZE(iovstack), &iov, &from); > > - if (ret < 0) > > - return ret; > > - > > pipe_lock(pipe); > > ret = wait_for_space(pipe, flags); > > if (!ret) > > - ret = iter_to_pipe(&from, pipe, buf_flag); > > + ret = iter_to_pipe(iter, pipe, buf_flag); > > pipe_unlock(pipe); > > if (ret > 0) > > wakeup_pipe_readers(pipe); > > - kfree(iov); > > return ret; > > } > > > > @@ -1331,29 +1310,39 @@ static long vmsplice_to_pipe(struct file *file, const struct iovec __user *uiov, > > * Currently we punt and implement it as a normal copy, see pipe_to_user(). > > * > > */ > > -static long do_vmsplice(int fd, const struct iovec __user *iov, > > +static long do_vmsplice(int fd, const struct iovec __user *uiov, > > unsigned long nr_segs, unsigned int flags) > > { > > + struct iovec iovstack[UIO_FASTIOV]; > > + struct iovec *iov = iovstack; > > + struct iov_iter iter; > > struct fd f; > > long error; > > > > if (unlikely(flags & ~SPLICE_F_ALL)) > > return -EINVAL; > > - if (unlikely(nr_segs > UIO_MAXIOV)) > > - return -EINVAL; > > - else if (unlikely(!nr_segs)) > > + > > + error = import_iovec(READ, uiov, nr_segs, > > + ARRAY_SIZE(iovstack), &iov, &iter); > > import_iovec should be called with WRITE, if we are going to call > vmsplice_to_pipe(). We caught this issue, when we run CRIU tests for https://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs.git/log/?h=for-next CRIU fails with errors like this: pie: 38: Error (criu/pie/parasite.c:89): Can't splice pages to pipe (-14/2/0) Thanks, Andrei > > > + if (error < 0) > > + return error; > > + > > + if (!iov_iter_count(&iter)) { > > + kfree(iov); > > return 0; > > + } > > > > error = -EBADF; > > f = fdget(fd); > > if (f.file) { > > if (f.file->f_mode & FMODE_WRITE) > > - error = vmsplice_to_pipe(f.file, iov, nr_segs, flags); > > + error = vmsplice_to_pipe(f.file, &iter, flags); > > else if (f.file->f_mode & FMODE_READ) > > - error = vmsplice_to_user(f.file, iov, nr_segs, flags); > > + error = vmsplice_to_user(f.file, &iter, flags); > > > > fdput(f); > > } > > + kfree(iov); > > > > return error; > > }