diff options
author | Jens Axboe <axboe@kernel.dk> | 2023-03-24 14:37:19 -0600 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2023-03-30 08:12:29 -0600 |
commit | 3b2deb0e46da9798b694cf50bd8bea1b26dcc789 (patch) | |
tree | 9674a8f8ad1ae25466700d45580d1f2562926716 /lib/iov_iter.c | |
parent | e03ad4ee2783e41afc90cc7848468aef10741c0e (diff) |
iov_iter: import single vector iovecs as ITER_UBUF
Add a special case to __import_iovec(), which imports a single segment
iovec as an ITER_UBUF rather than an ITER_IOVEC. ITER_UBUF is cheaper
to iterate than ITER_IOVEC, and for a single segment iovec, there's no
point in using a segmented iterator.
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'lib/iov_iter.c')
-rw-r--r-- | lib/iov_iter.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/lib/iov_iter.c b/lib/iov_iter.c index f411bda1171f..3e6c9bcfa612 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c @@ -1784,6 +1784,30 @@ struct iovec *iovec_from_user(const struct iovec __user *uvec, return iov; } +/* + * Single segment iovec supplied by the user, import it as ITER_UBUF. + */ +static ssize_t __import_iovec_ubuf(int type, const struct iovec __user *uvec, + struct iovec **iovp, struct iov_iter *i, + bool compat) +{ + struct iovec *iov = *iovp; + ssize_t ret; + + if (compat) + ret = copy_compat_iovec_from_user(iov, uvec, 1); + else + ret = copy_iovec_from_user(iov, uvec, 1); + if (unlikely(ret)) + return ret; + + ret = import_ubuf(type, iov->iov_base, iov->iov_len, i); + if (unlikely(ret)) + return ret; + *iovp = NULL; + return i->count; +} + ssize_t __import_iovec(int type, const struct iovec __user *uvec, unsigned nr_segs, unsigned fast_segs, struct iovec **iovp, struct iov_iter *i, bool compat) @@ -1792,6 +1816,9 @@ ssize_t __import_iovec(int type, const struct iovec __user *uvec, unsigned long seg; struct iovec *iov; + if (nr_segs == 1) + return __import_iovec_ubuf(type, uvec, iovp, i, compat); + iov = iovec_from_user(uvec, nr_segs, fast_segs, *iovp, compat); if (IS_ERR(iov)) { *iovp = NULL; |