summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2022-06-11 02:38:20 +0200
committerAl Viro <viro@zeniv.linux.org.uk>2022-08-09 04:37:19 +0200
commit91329559eb07c9b12c7ce80e893ad39579c40aa2 (patch)
tree854e4d968710ff776aa85bc57fb560b5f0114adf /lib
parentITER_PIPE: fold data_start() and pipe_space_for_user() together (diff)
downloadlinux-91329559eb07c9b12c7ce80e893ad39579c40aa2.tar.xz
linux-91329559eb07c9b12c7ce80e893ad39579c40aa2.zip
iov_iter_get_pages_alloc(): lift freeing pages array on failure exits into wrapper
Incidentally, ITER_XARRAY did *not* free the sucker in case when iter_xarray_populate_pages() returned 0... Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'lib')
-rw-r--r--lib/iov_iter.c38
1 files changed, 22 insertions, 16 deletions
diff --git a/lib/iov_iter.c b/lib/iov_iter.c
index 12dda1013bea..e14749711e34 100644
--- a/lib/iov_iter.c
+++ b/lib/iov_iter.c
@@ -1506,15 +1506,10 @@ static ssize_t pipe_get_pages_alloc(struct iov_iter *i,
maxsize = n;
else
npages = DIV_ROUND_UP(maxsize + off, PAGE_SIZE);
- p = get_pages_array(npages);
+ *pages = p = get_pages_array(npages);
if (!p)
return -ENOMEM;
- n = __pipe_get_pages(i, maxsize, p, off);
- if (n > 0)
- *pages = p;
- else
- kvfree(p);
- return n;
+ return __pipe_get_pages(i, maxsize, p, off);
}
static ssize_t iter_xarray_get_pages_alloc(struct iov_iter *i,
@@ -1544,10 +1539,9 @@ static ssize_t iter_xarray_get_pages_alloc(struct iov_iter *i,
count++;
}
- p = get_pages_array(count);
+ *pages = p = get_pages_array(count);
if (!p)
return -ENOMEM;
- *pages = p;
nr = iter_xarray_populate_pages(p, i->xarray, index, count);
if (nr == 0)
@@ -1556,7 +1550,7 @@ static ssize_t iter_xarray_get_pages_alloc(struct iov_iter *i,
return min_t(size_t, nr * PAGE_SIZE - offset, maxsize);
}
-ssize_t iov_iter_get_pages_alloc(struct iov_iter *i,
+static ssize_t __iov_iter_get_pages_alloc(struct iov_iter *i,
struct page ***pages, size_t maxsize,
size_t *start)
{
@@ -1583,16 +1577,12 @@ ssize_t iov_iter_get_pages_alloc(struct iov_iter *i,
*start = addr % PAGE_SIZE;
addr &= PAGE_MASK;
n = DIV_ROUND_UP(maxsize + *start, PAGE_SIZE);
- p = get_pages_array(n);
+ *pages = p = get_pages_array(n);
if (!p)
return -ENOMEM;
res = get_user_pages_fast(addr, n, gup_flags, p);
- if (unlikely(res <= 0)) {
- kvfree(p);
- *pages = NULL;
+ if (unlikely(res <= 0))
return res;
- }
- *pages = p;
return min_t(size_t, maxsize, res * PAGE_SIZE - *start);
}
if (iov_iter_is_bvec(i)) {
@@ -1613,6 +1603,22 @@ ssize_t iov_iter_get_pages_alloc(struct iov_iter *i,
return iter_xarray_get_pages_alloc(i, pages, maxsize, start);
return -EFAULT;
}
+
+ssize_t iov_iter_get_pages_alloc(struct iov_iter *i,
+ struct page ***pages, size_t maxsize,
+ size_t *start)
+{
+ ssize_t len;
+
+ *pages = NULL;
+
+ len = __iov_iter_get_pages_alloc(i, pages, maxsize, start);
+ if (len <= 0) {
+ kvfree(*pages);
+ *pages = NULL;
+ }
+ return len;
+}
EXPORT_SYMBOL(iov_iter_get_pages_alloc);
size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum,