diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2014-03-19 01:16:16 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2014-05-06 17:32:52 -0400 |
commit | f67da30c1d5fc9e341bc8121708874bfd7b31e45 (patch) | |
tree | 504966ed27e82dbcbe31786c9a0851a4ae79ef3e /mm | |
parent | 5b46f25ddc6edf4adff1a137d453da542c27a640 (diff) |
new helper: iov_iter_npages()
counts the pages covered by iov_iter, up to given limit.
do_block_direct_io() and fuse_iter_npages() switched to
it.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/iov_iter.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/mm/iov_iter.c b/mm/iov_iter.c index 45204cd5ccd8..0b677f8f9bad 100644 --- a/mm/iov_iter.c +++ b/mm/iov_iter.c | |||
@@ -262,3 +262,30 @@ ssize_t iov_iter_get_pages(struct iov_iter *i, | |||
262 | return (res == n ? len : res * PAGE_SIZE) - *start; | 262 | return (res == n ? len : res * PAGE_SIZE) - *start; |
263 | } | 263 | } |
264 | EXPORT_SYMBOL(iov_iter_get_pages); | 264 | EXPORT_SYMBOL(iov_iter_get_pages); |
265 | |||
266 | int iov_iter_npages(const struct iov_iter *i, int maxpages) | ||
267 | { | ||
268 | size_t offset = i->iov_offset; | ||
269 | size_t size = i->count; | ||
270 | const struct iovec *iov = i->iov; | ||
271 | int npages = 0; | ||
272 | int n; | ||
273 | |||
274 | for (n = 0; size && n < i->nr_segs; n++, iov++) { | ||
275 | unsigned long addr = (unsigned long)iov->iov_base + offset; | ||
276 | size_t len = iov->iov_len - offset; | ||
277 | offset = 0; | ||
278 | if (unlikely(!len)) /* empty segment */ | ||
279 | continue; | ||
280 | if (len > size) | ||
281 | len = size; | ||
282 | npages += (addr + len + PAGE_SIZE - 1) / PAGE_SIZE | ||
283 | - addr / PAGE_SIZE; | ||
284 | if (npages >= maxpages) /* don't bother going further */ | ||
285 | return maxpages; | ||
286 | size -= len; | ||
287 | offset = 0; | ||
288 | } | ||
289 | return min(npages, maxpages); | ||
290 | } | ||
291 | EXPORT_SYMBOL(iov_iter_npages); | ||