Commit 171a0203 authored by Anton Altaparmakov's avatar Anton Altaparmakov Committed by Al Viro

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: default avatarAnton Altaparmakov <anton@tuxera.com>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent e5b811e3
...@@ -76,6 +76,7 @@ size_t iov_iter_copy_from_user_atomic(struct page *page, ...@@ -76,6 +76,7 @@ size_t iov_iter_copy_from_user_atomic(struct page *page,
struct iov_iter *i, unsigned long offset, size_t bytes); struct iov_iter *i, unsigned long offset, size_t bytes);
void iov_iter_advance(struct iov_iter *i, size_t bytes); void iov_iter_advance(struct iov_iter *i, size_t bytes);
int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes); int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes);
int iov_iter_fault_in_multipages_readable(struct iov_iter *i, size_t bytes);
size_t iov_iter_single_seg_count(const struct iov_iter *i); size_t iov_iter_single_seg_count(const struct iov_iter *i);
size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes, size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes,
struct iov_iter *i); struct iov_iter *i);
......
...@@ -317,6 +317,32 @@ int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes) ...@@ -317,6 +317,32 @@ int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes)
} }
EXPORT_SYMBOL(iov_iter_fault_in_readable); 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, void iov_iter_init(struct iov_iter *i, int direction,
const struct iovec *iov, unsigned long nr_segs, const struct iovec *iov, unsigned long nr_segs,
size_t count) size_t count)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment