Commit 91329559 authored by Al Viro's avatar Al Viro

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: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 12d426ab
...@@ -1506,15 +1506,10 @@ static ssize_t pipe_get_pages_alloc(struct iov_iter *i, ...@@ -1506,15 +1506,10 @@ static ssize_t pipe_get_pages_alloc(struct iov_iter *i,
maxsize = n; maxsize = n;
else else
npages = DIV_ROUND_UP(maxsize + off, PAGE_SIZE); npages = DIV_ROUND_UP(maxsize + off, PAGE_SIZE);
p = get_pages_array(npages); *pages = p = get_pages_array(npages);
if (!p) if (!p)
return -ENOMEM; return -ENOMEM;
n = __pipe_get_pages(i, maxsize, p, off); return __pipe_get_pages(i, maxsize, p, off);
if (n > 0)
*pages = p;
else
kvfree(p);
return n;
} }
static ssize_t iter_xarray_get_pages_alloc(struct iov_iter *i, 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, ...@@ -1544,10 +1539,9 @@ static ssize_t iter_xarray_get_pages_alloc(struct iov_iter *i,
count++; count++;
} }
p = get_pages_array(count); *pages = p = get_pages_array(count);
if (!p) if (!p)
return -ENOMEM; return -ENOMEM;
*pages = p;
nr = iter_xarray_populate_pages(p, i->xarray, index, count); nr = iter_xarray_populate_pages(p, i->xarray, index, count);
if (nr == 0) if (nr == 0)
...@@ -1556,7 +1550,7 @@ static ssize_t iter_xarray_get_pages_alloc(struct iov_iter *i, ...@@ -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); 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, struct page ***pages, size_t maxsize,
size_t *start) size_t *start)
{ {
...@@ -1583,16 +1577,12 @@ ssize_t iov_iter_get_pages_alloc(struct iov_iter *i, ...@@ -1583,16 +1577,12 @@ ssize_t iov_iter_get_pages_alloc(struct iov_iter *i,
*start = addr % PAGE_SIZE; *start = addr % PAGE_SIZE;
addr &= PAGE_MASK; addr &= PAGE_MASK;
n = DIV_ROUND_UP(maxsize + *start, PAGE_SIZE); n = DIV_ROUND_UP(maxsize + *start, PAGE_SIZE);
p = get_pages_array(n); *pages = p = get_pages_array(n);
if (!p) if (!p)
return -ENOMEM; return -ENOMEM;
res = get_user_pages_fast(addr, n, gup_flags, p); res = get_user_pages_fast(addr, n, gup_flags, p);
if (unlikely(res <= 0)) { if (unlikely(res <= 0))
kvfree(p);
*pages = NULL;
return res; return res;
}
*pages = p;
return min_t(size_t, maxsize, res * PAGE_SIZE - *start); return min_t(size_t, maxsize, res * PAGE_SIZE - *start);
} }
if (iov_iter_is_bvec(i)) { if (iov_iter_is_bvec(i)) {
...@@ -1613,6 +1603,22 @@ ssize_t iov_iter_get_pages_alloc(struct iov_iter *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 iter_xarray_get_pages_alloc(i, pages, maxsize, start);
return -EFAULT; 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); EXPORT_SYMBOL(iov_iter_get_pages_alloc);
size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment