summaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2014-03-15 04:05:57 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2014-05-06 17:32:50 -0400
commit7b2c99d15559e285384c742db52316802e24b0bd (patch)
tree0f5260039ca25431decd1affc281aea5a5da27da /mm
parent3320c60b3a26d05666285c55ab08ee043c017ba3 (diff)
new helper: iov_iter_get_pages()
iov_iter_get_pages(iter, pages, maxsize, &start) grabs references pinning the pages of up to maxsize of (contiguous) data from iter. Returns the amount of memory grabbed or -error. In case of success, the requested area begins at offset start in pages[0] and runs through pages[1], etc. Less than requested amount might be returned - either because the contiguous area in the beginning of iterator is smaller than requested, or because the kernel failed to pin that many pages. direct-io.c switched to using iov_iter_get_pages() Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'mm')
-rw-r--r--mm/iov_iter.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/mm/iov_iter.c b/mm/iov_iter.c
index e2c9a2db4350..45204cd5ccd8 100644
--- a/mm/iov_iter.c
+++ b/mm/iov_iter.c
@@ -235,3 +235,30 @@ void iov_iter_init(struct iov_iter *i, int direction,
235 i->count = count; 235 i->count = count;
236} 236}
237EXPORT_SYMBOL(iov_iter_init); 237EXPORT_SYMBOL(iov_iter_init);
238
239ssize_t iov_iter_get_pages(struct iov_iter *i,
240 struct page **pages, size_t maxsize,
241 size_t *start)
242{
243 size_t offset = i->iov_offset;
244 const struct iovec *iov = i->iov;
245 size_t len;
246 unsigned long addr;
247 int n;
248 int res;
249
250 len = iov->iov_len - offset;
251 if (len > i->count)
252 len = i->count;
253 if (len > maxsize)
254 len = maxsize;
255 addr = (unsigned long)iov->iov_base + offset;
256 len += *start = addr & (PAGE_SIZE - 1);
257 addr &= ~(PAGE_SIZE - 1);
258 n = (len + PAGE_SIZE - 1) / PAGE_SIZE;
259 res = get_user_pages_fast(addr, n, (i->type & WRITE) != WRITE, pages);
260 if (unlikely(res < 0))
261 return res;
262 return (res == n ? len : res * PAGE_SIZE) - *start;
263}
264EXPORT_SYMBOL(iov_iter_get_pages);