diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2014-11-28 02:27:08 +0100 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2014-12-09 02:25:23 +0100 |
commit | aa583096d9767892983332e7c1a984bd17e3cd39 (patch) | |
tree | 0a95463b6a62365ee6e37a8f2f4258ad7073197a | |
parent | new helper: iov_iter_kvec() (diff) | |
download | linux-aa583096d9767892983332e7c1a984bd17e3cd39.tar.xz linux-aa583096d9767892983332e7c1a984bd17e3cd39.zip |
copy_from_iter_nocache()
BTW, do we want memcpy_nocache()?
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | include/linux/uio.h | 1 | ||||
-rw-r--r-- | mm/iov_iter.c | 21 |
2 files changed, 22 insertions, 0 deletions
diff --git a/include/linux/uio.h b/include/linux/uio.h index c567655b9595..bd8569a14c4a 100644 --- a/include/linux/uio.h +++ b/include/linux/uio.h @@ -83,6 +83,7 @@ size_t copy_page_from_iter(struct page *page, size_t offset, size_t bytes, struct iov_iter *i); size_t copy_to_iter(void *addr, size_t bytes, struct iov_iter *i); size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i); +size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i); size_t iov_iter_zero(size_t bytes, struct iov_iter *); unsigned long iov_iter_alignment(const struct iov_iter *i); void iov_iter_init(struct iov_iter *i, int direction, const struct iovec *iov, diff --git a/mm/iov_iter.c b/mm/iov_iter.c index 88c052e63a1d..a1599ca4ab0e 100644 --- a/mm/iov_iter.c +++ b/mm/iov_iter.c @@ -399,6 +399,27 @@ size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i) } EXPORT_SYMBOL(copy_from_iter); +size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i) +{ + char *to = addr; + if (unlikely(bytes > i->count)) + bytes = i->count; + + if (unlikely(!bytes)) + return 0; + + iterate_and_advance(i, bytes, v, + __copy_from_user_nocache((to += v.iov_len) - v.iov_len, + v.iov_base, v.iov_len), + memcpy_from_page((to += v.bv_len) - v.bv_len, v.bv_page, + v.bv_offset, v.bv_len), + memcpy((to += v.iov_len) - v.iov_len, v.iov_base, v.iov_len) + ) + + return bytes; +} +EXPORT_SYMBOL(copy_from_iter_nocache); + size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes, struct iov_iter *i) { |