[RFC,iov_iter v2 3/8] iov_iter: add copyin_iovec helper

From: Joe Damato
Date: Sun Jun 12 2022 - 05:00:55 EST


copyin_iovec is a helper which wraps copyin and selects the right copy
method based on the iter_copy_type.

Signed-off-by: Joe Damato <jdamato@xxxxxxxxxx>
---
lib/iov_iter.c | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/lib/iov_iter.c b/lib/iov_iter.c
index d32d7e5..6720cb2 100644
--- a/lib/iov_iter.c
+++ b/lib/iov_iter.c
@@ -168,6 +168,15 @@ static int copyin(void *to, const void __user *from, size_t n)
return n;
}

+static int copyin_iovec(void *to, const void __user *from, size_t n,
+ struct iov_iter *i)
+{
+ if (unlikely(iov_iter_copy_is_nt(i)))
+ return __copy_from_user_nocache(to, from, n);
+ else
+ return copyin(to, from, n);
+}
+
static size_t copy_page_to_iter_iovec(struct page *page, size_t offset, size_t bytes,
struct iov_iter *i)
{
@@ -278,7 +287,7 @@ static size_t copy_page_from_iter_iovec(struct page *page, size_t offset, size_t
to = kaddr + offset;

/* first chunk, usually the only one */
- left = copyin(to, buf, copy);
+ left = copyin_iovec(to, buf, copy, i);
copy -= left;
skip += copy;
to += copy;
@@ -288,7 +297,7 @@ static size_t copy_page_from_iter_iovec(struct page *page, size_t offset, size_t
iov++;
buf = iov->iov_base;
copy = min(bytes, iov->iov_len);
- left = copyin(to, buf, copy);
+ left = copyin_iovec(to, buf, copy, i);
copy -= left;
skip = copy;
to += copy;
@@ -307,7 +316,7 @@ static size_t copy_page_from_iter_iovec(struct page *page, size_t offset, size_t

kaddr = kmap(page);
to = kaddr + offset;
- left = copyin(to, buf, copy);
+ left = copyin_iovec(to, buf, copy, i);
copy -= left;
skip += copy;
to += copy;
@@ -316,7 +325,7 @@ static size_t copy_page_from_iter_iovec(struct page *page, size_t offset, size_t
iov++;
buf = iov->iov_base;
copy = min(bytes, iov->iov_len);
- left = copyin(to, buf, copy);
+ left = copyin_iovec(to, buf, copy, i);
copy -= left;
skip = copy;
to += copy;
@@ -766,7 +775,7 @@ size_t _copy_from_iter(void *addr, size_t bytes, struct iov_iter *i)
if (iter_is_iovec(i))
might_fault();
iterate_and_advance(i, bytes, base, len, off,
- copyin(addr + off, base, len),
+ copyin_iovec(addr + off, base, len, i),
memcpy(addr + off, base, len)
)

--
2.7.4