From: David Laight <David.Laight@xxxxxxxxxx> This is the only direct call of rw_copy_check_uvector(). Removing it will allow rw_copy_check_uvector() to be inlined into import_iovec(), while only paying a minor price by setting up an otherwise unused iov_iter in the process_vm_readv/process_vm_writev syscalls that aren't in a super hot path. Signed-off-by: David Laight <david.laight@xxxxxxxxxx> [hch: expanded the commit log, pass CHECK_IOVEC_ONLY instead of 0 for the compat case, handle CHECK_IOVEC_ONLY in iov_iter_init] Signed-off-by: Christoph Hellwig <hch@xxxxxx> --- lib/iov_iter.c | 2 +- mm/process_vm_access.c | 33 ++++++++++++++++++--------------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/lib/iov_iter.c b/lib/iov_iter.c index 5e40786c8f1232..db54588406dfae 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c @@ -443,7 +443,7 @@ void iov_iter_init(struct iov_iter *i, unsigned int direction, const struct iovec *iov, unsigned long nr_segs, size_t count) { - WARN_ON(direction & ~(READ | WRITE)); + WARN_ON(direction & ~(READ | WRITE | CHECK_IOVEC_ONLY)); direction &= READ | WRITE; /* It will get better. Eventually... */ diff --git a/mm/process_vm_access.c b/mm/process_vm_access.c index 29c052099affdc..40cd502c337534 100644 --- a/mm/process_vm_access.c +++ b/mm/process_vm_access.c @@ -264,7 +264,7 @@ static ssize_t process_vm_rw(pid_t pid, struct iovec iovstack_r[UIO_FASTIOV]; struct iovec *iov_l = iovstack_l; struct iovec *iov_r = iovstack_r; - struct iov_iter iter; + struct iov_iter iter_l, iter_r; ssize_t rc; int dir = vm_write ? WRITE : READ; @@ -272,23 +272,25 @@ static ssize_t process_vm_rw(pid_t pid, return -EINVAL; /* Check iovecs */ - rc = import_iovec(dir, lvec, liovcnt, UIO_FASTIOV, &iov_l, &iter); + rc = import_iovec(dir, lvec, liovcnt, UIO_FASTIOV, &iov_l, &iter_l); if (rc < 0) return rc; - if (!iov_iter_count(&iter)) + if (!iov_iter_count(&iter_l)) goto free_iovecs; - rc = rw_copy_check_uvector(CHECK_IOVEC_ONLY, rvec, riovcnt, UIO_FASTIOV, - iovstack_r, &iov_r); + rc = import_iovec(CHECK_IOVEC_ONLY, rvec, riovcnt, UIO_FASTIOV, &iov_r, + &iter_r); if (rc <= 0) goto free_iovecs; - rc = process_vm_rw_core(pid, &iter, iov_r, riovcnt, flags, vm_write); + rc = process_vm_rw_core(pid, &iter_l, iter_r.iov, iter_r.nr_segs, + flags, vm_write); free_iovecs: if (iov_r != iovstack_r) kfree(iov_r); - kfree(iov_l); + if (iov_l != iovstack_l) + kfree(iov_l); return rc; } @@ -322,30 +324,31 @@ compat_process_vm_rw(compat_pid_t pid, struct iovec iovstack_r[UIO_FASTIOV]; struct iovec *iov_l = iovstack_l; struct iovec *iov_r = iovstack_r; - struct iov_iter iter; + struct iov_iter iter_l, iter_r; ssize_t rc = -EFAULT; int dir = vm_write ? WRITE : READ; if (flags != 0) return -EINVAL; - rc = compat_import_iovec(dir, lvec, liovcnt, UIO_FASTIOV, &iov_l, &iter); + rc = compat_import_iovec(dir, lvec, liovcnt, UIO_FASTIOV, &iov_l, &iter_l); if (rc < 0) return rc; - if (!iov_iter_count(&iter)) + if (!iov_iter_count(&iter_l)) goto free_iovecs; - rc = compat_rw_copy_check_uvector(CHECK_IOVEC_ONLY, rvec, riovcnt, - UIO_FASTIOV, iovstack_r, - &iov_r); + rc = compat_import_iovec(CHECK_IOVEC_ONLY, rvec, riovcnt, UIO_FASTIOV, + &iov_r, &iter_r); if (rc <= 0) goto free_iovecs; - rc = process_vm_rw_core(pid, &iter, iov_r, riovcnt, flags, vm_write); + rc = process_vm_rw_core(pid, &iter_l, iter_r.iov, iter_r.nr_segs, + flags, vm_write); free_iovecs: if (iov_r != iovstack_r) kfree(iov_r); - kfree(iov_l); + if (iov_l != iovstack_l) + kfree(iov_l); return rc; } -- 2.28.0