iov_iter.c: convert iov_iter_get_pages() to iterate_all_kinds
authorAl Viro <viro@zeniv.linux.org.uk>
Thu, 27 Nov 2014 19:12:09 +0000 (14:12 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Thu, 27 Nov 2014 23:44:11 +0000 (18:44 -0500)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
mm/iov_iter.c

index bc666e79b5bd4677f0dadd1314d47b846f932b98..75e29ef59b0e026c24c2290c3dcf37d67019ea08 100644 (file)
@@ -428,34 +428,6 @@ void iov_iter_init(struct iov_iter *i, int direction,
 }
 EXPORT_SYMBOL(iov_iter_init);
 
-static ssize_t get_pages_iovec(struct iov_iter *i,
-                  struct page **pages, size_t maxsize, unsigned maxpages,
-                  size_t *start)
-{
-       size_t offset = i->iov_offset;
-       const struct iovec *iov = i->iov;
-       size_t len;
-       unsigned long addr;
-       int n;
-       int res;
-
-       len = iov->iov_len - offset;
-       if (len > i->count)
-               len = i->count;
-       if (len > maxsize)
-               len = maxsize;
-       addr = (unsigned long)iov->iov_base + offset;
-       len += *start = addr & (PAGE_SIZE - 1);
-       if (len > maxpages * PAGE_SIZE)
-               len = maxpages * PAGE_SIZE;
-       addr &= ~(PAGE_SIZE - 1);
-       n = (len + PAGE_SIZE - 1) / PAGE_SIZE;
-       res = get_user_pages_fast(addr, n, (i->type & WRITE) != WRITE, pages);
-       if (unlikely(res < 0))
-               return res;
-       return (res == n ? len : res * PAGE_SIZE) - *start;
-}
-
 static ssize_t get_pages_alloc_iovec(struct iov_iter *i,
                   struct page ***pages, size_t maxsize,
                   size_t *start)
@@ -650,24 +622,6 @@ static size_t zero_bvec(size_t bytes, struct iov_iter *i)
        return wanted - bytes;
 }
 
-static ssize_t get_pages_bvec(struct iov_iter *i,
-                  struct page **pages, size_t maxsize, unsigned maxpages,
-                  size_t *start)
-{
-       const struct bio_vec *bvec = i->bvec;
-       size_t len = bvec->bv_len - i->iov_offset;
-       if (len > i->count)
-               len = i->count;
-       if (len > maxsize)
-               len = maxsize;
-       /* can't be more than PAGE_SIZE */
-       *start = bvec->bv_offset + i->iov_offset;
-
-       get_page(*pages = bvec->bv_page);
-
-       return len;
-}
-
 static ssize_t get_pages_alloc_bvec(struct iov_iter *i,
                   struct page ***pages, size_t maxsize,
                   size_t *start)
@@ -792,10 +746,34 @@ ssize_t iov_iter_get_pages(struct iov_iter *i,
                   struct page **pages, size_t maxsize, unsigned maxpages,
                   size_t *start)
 {
-       if (i->type & ITER_BVEC)
-               return get_pages_bvec(i, pages, maxsize, maxpages, start);
-       else
-               return get_pages_iovec(i, pages, maxsize, maxpages, start);
+       if (maxsize > i->count)
+               maxsize = i->count;
+
+       if (!maxsize)
+               return 0;
+
+       iterate_all_kinds(i, maxsize, v, ({
+               unsigned long addr = (unsigned long)v.iov_base;
+               size_t len = v.iov_len + (*start = addr & (PAGE_SIZE - 1));
+               int n;
+               int res;
+
+               if (len > maxpages * PAGE_SIZE)
+                       len = maxpages * PAGE_SIZE;
+               addr &= ~(PAGE_SIZE - 1);
+               n = DIV_ROUND_UP(len, PAGE_SIZE);
+               res = get_user_pages_fast(addr, n, (i->type & WRITE) != WRITE, pages);
+               if (unlikely(res < 0))
+                       return res;
+               return (res == n ? len : res * PAGE_SIZE) - *start;
+       0;}),({
+               /* can't be more than PAGE_SIZE */
+               *start = v.bv_offset;
+               get_page(*pages = v.bv_page);
+               return v.bv_len;
+       })
+       )
+       return 0;
 }
 EXPORT_SYMBOL(iov_iter_get_pages);