summaryrefslogtreecommitdiffstats
path: root/lib/iov_iter.c
diff options
context:
space:
mode:
authorAnton Altaparmakov <anton@tuxera.com>2015-03-11 10:43:31 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2015-04-11 22:24:32 -0400
commit171a02032bf1e1bb35442a38d6e25e0dcbb85c63 (patch)
treea374f6fcd3290ccce1872c6013799dc8c171a31e /lib/iov_iter.c
parente5b811e38af7540b385c898d83eb0198310343fd (diff)
downloadlinux-stable-171a02032bf1e1bb35442a38d6e25e0dcbb85c63.tar.gz
linux-stable-171a02032bf1e1bb35442a38d6e25e0dcbb85c63.tar.bz2
linux-stable-171a02032bf1e1bb35442a38d6e25e0dcbb85c63.zip
VFS: Add iov_iter_fault_in_multipages_readable()
simillar to iov_iter_fault_in_readable() but differs in that it is not limited to faulting in the first iovec and instead faults in "bytes" bytes iterating over the iovecs as necessary. Also, instead of only faulting in the first and last page of the range, all pages are faulted in. This function is needed by NTFS when it does multi page file writes. Signed-off-by: Anton Altaparmakov <anton@tuxera.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'lib/iov_iter.c')
-rw-r--r--lib/iov_iter.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/lib/iov_iter.c b/lib/iov_iter.c
index 9d96e283520c..b80f84376b91 100644
--- a/lib/iov_iter.c
+++ b/lib/iov_iter.c
@@ -317,6 +317,32 @@ int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes)
}
EXPORT_SYMBOL(iov_iter_fault_in_readable);
+/*
+ * Fault in one or more iovecs of the given iov_iter, to a maximum length of
+ * bytes. For each iovec, fault in each page that constitutes the iovec.
+ *
+ * Return 0 on success, or non-zero if the memory could not be accessed (i.e.
+ * because it is an invalid address).
+ */
+int iov_iter_fault_in_multipages_readable(struct iov_iter *i, size_t bytes)
+{
+ size_t skip = i->iov_offset;
+ const struct iovec *iov;
+ int err;
+ struct iovec v;
+
+ if (!(i->type & (ITER_BVEC|ITER_KVEC))) {
+ iterate_iovec(i, bytes, v, iov, skip, ({
+ err = fault_in_multipages_readable(v.iov_base,
+ v.iov_len);
+ if (unlikely(err))
+ return err;
+ 0;}))
+ }
+ return 0;
+}
+EXPORT_SYMBOL(iov_iter_fault_in_multipages_readable);
+
void iov_iter_init(struct iov_iter *i, int direction,
const struct iovec *iov, unsigned long nr_segs,
size_t count)