[braino fix] >From e64d637d648390e4ac0643747ae174c3be15f243 Mon Sep 17 00:00:00 2001 From: Al Viro <viro@xxxxxxxxxxxxxxxxxx> Date: Fri, 17 Jun 2022 14:45:41 -0400 Subject: [PATCH 22/31] iov_iter: saner helper for page array allocation All call sites of get_pages_array() are essenitally identical now. Replace with common helper... Signed-off-by: Al Viro <viro@xxxxxxxxxxxxxxxxxx> --- lib/iov_iter.c | 64 +++++++++++++++++++------------------------------- 1 file changed, 24 insertions(+), 40 deletions(-) diff --git a/lib/iov_iter.c b/lib/iov_iter.c index a65c766936cc..2ce062f1817d 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c @@ -1187,9 +1187,19 @@ unsigned long iov_iter_gap_alignment(const struct iov_iter *i) } EXPORT_SYMBOL(iov_iter_gap_alignment); -static struct page **get_pages_array(size_t n) +static int want_pages_array(struct page ***res, size_t size, + size_t start, unsigned int maxpages) { - return kvmalloc_array(n, sizeof(struct page *), GFP_KERNEL); + unsigned count = DIV_ROUND_UP(size + start, PAGE_SIZE); + + if (count > maxpages) + count = maxpages; + if (!*res) { + *res = kvmalloc_array(count, sizeof(struct page *), GFP_KERNEL); + if (!*res) + return -ENOMEM; + } + return count; } static ssize_t pipe_get_pages(struct iov_iter *i, @@ -1206,18 +1216,10 @@ static ssize_t pipe_get_pages(struct iov_iter *i, return -EFAULT; *start = off = pipe_npages(i, &npages); - count = DIV_ROUND_UP(maxsize + off, PAGE_SIZE); - if (count > npages) - count = npages; - if (count > maxpages) - count = maxpages; + count = want_pages_array(pages, maxsize, off, min(npages, maxpages)); + if (count < 0) + return count; p = *pages; - if (!p) { - *pages = p = get_pages_array(count); - if (!p) - return -ENOMEM; - } - left = maxsize; npages = 0; if (off) { @@ -1282,7 +1284,6 @@ static ssize_t iter_xarray_get_pages(struct iov_iter *i, { unsigned nr, offset; pgoff_t index, count; - size_t size = maxsize; loff_t pos; pos = i->xarray_start + i->iov_offset; @@ -1290,16 +1291,9 @@ static ssize_t iter_xarray_get_pages(struct iov_iter *i, offset = pos & ~PAGE_MASK; *_start_offset = offset; - count = DIV_ROUND_UP(size + offset, PAGE_SIZE); - if (count > maxpages) - count = maxpages; - - if (!*pages) { - *pages = get_pages_array(count); - if (!*pages) - return -ENOMEM; - } - + count = want_pages_array(pages, maxsize, offset, maxpages); + if (count < 0) + return count; nr = iter_xarray_populate_pages(*pages, i->xarray, index, count); if (nr == 0) return 0; @@ -1369,14 +1363,9 @@ static ssize_t __iov_iter_get_pages_alloc(struct iov_iter *i, addr = first_iovec_segment(i, &maxsize); *start = addr % PAGE_SIZE; addr &= PAGE_MASK; - n = DIV_ROUND_UP(maxsize + *start, PAGE_SIZE); - if (n > maxpages) - n = maxpages; - if (*pages) { - *pages = get_pages_array(n); - if (!*pages) - return -ENOMEM; - } + n = want_pages_array(pages, maxsize, *start, maxpages); + if (n < 0) + return n; res = get_user_pages_fast(addr, n, gup_flags, *pages); if (unlikely(res <= 0)) return res; @@ -1387,15 +1376,10 @@ static ssize_t __iov_iter_get_pages_alloc(struct iov_iter *i, struct page *page; page = first_bvec_segment(i, &maxsize, start); - n = DIV_ROUND_UP(maxsize + *start, PAGE_SIZE); - if (n > maxpages) - n = maxpages; + n = want_pages_array(pages, maxsize, *start, maxpages); + if (n < 0) + return n; p = *pages; - if (!p) { - *pages = p = get_pages_array(n); - if (!p) - return -ENOMEM; - } for (int k = 0; k < n; k++) get_page(*p++ = page++); return min_t(size_t, maxsize, n * PAGE_SIZE - *start); -- 2.30.2