iov_iter: massage calling conventions for first_{iovec,bvec}_segment()

Pass maxsize by reference, return length via the same.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Al Viro 2022-06-21 16:10:37 -04:00
Родитель dda8e5d17c
Коммит 59dbd7d090
1 изменённых файлов: 18 добавлений и 24 удалений

Просмотреть файл

@ -1294,8 +1294,7 @@ static ssize_t iter_xarray_get_pages(struct iov_iter *i,
/* must be done on non-empty ITER_IOVEC one */ /* must be done on non-empty ITER_IOVEC one */
static unsigned long first_iovec_segment(const struct iov_iter *i, static unsigned long first_iovec_segment(const struct iov_iter *i,
size_t *size, size_t *start, size_t *size, size_t *start)
size_t maxsize)
{ {
size_t skip; size_t skip;
long k; long k;
@ -1306,10 +1305,9 @@ static unsigned long first_iovec_segment(const struct iov_iter *i,
if (unlikely(!len)) if (unlikely(!len))
continue; continue;
if (len > maxsize) if (*size > len)
len = maxsize; *size = len;
*start = addr % PAGE_SIZE; *start = addr % PAGE_SIZE;
*size = len;
return addr & PAGE_MASK; return addr & PAGE_MASK;
} }
BUG(); // if it had been empty, we wouldn't get called BUG(); // if it had been empty, we wouldn't get called
@ -1317,19 +1315,17 @@ static unsigned long first_iovec_segment(const struct iov_iter *i,
/* must be done on non-empty ITER_BVEC one */ /* must be done on non-empty ITER_BVEC one */
static struct page *first_bvec_segment(const struct iov_iter *i, static struct page *first_bvec_segment(const struct iov_iter *i,
size_t *size, size_t *start, size_t *size, size_t *start)
size_t maxsize)
{ {
struct page *page; struct page *page;
size_t skip = i->iov_offset, len; size_t skip = i->iov_offset, len;
len = i->bvec->bv_len - skip; len = i->bvec->bv_len - skip;
if (len > maxsize) if (*size > len)
len = maxsize; *size = len;
skip += i->bvec->bv_offset; skip += i->bvec->bv_offset;
page = i->bvec->bv_page + skip / PAGE_SIZE; page = i->bvec->bv_page + skip / PAGE_SIZE;
*start = skip % PAGE_SIZE; *start = skip % PAGE_SIZE;
*size = len;
return page; return page;
} }
@ -1337,7 +1333,6 @@ ssize_t iov_iter_get_pages(struct iov_iter *i,
struct page **pages, size_t maxsize, unsigned maxpages, struct page **pages, size_t maxsize, unsigned maxpages,
size_t *start) size_t *start)
{ {
size_t len;
int n, res; int n, res;
if (maxsize > i->count) if (maxsize > i->count)
@ -1356,25 +1351,25 @@ ssize_t iov_iter_get_pages(struct iov_iter *i,
if (i->nofault) if (i->nofault)
gup_flags |= FOLL_NOFAULT; gup_flags |= FOLL_NOFAULT;
addr = first_iovec_segment(i, &len, start, maxsize); addr = first_iovec_segment(i, &maxsize, start);
n = DIV_ROUND_UP(len + *start, PAGE_SIZE); n = DIV_ROUND_UP(maxsize + *start, PAGE_SIZE);
if (n > maxpages) if (n > maxpages)
n = maxpages; n = maxpages;
res = get_user_pages_fast(addr, n, gup_flags, pages); res = get_user_pages_fast(addr, n, gup_flags, pages);
if (unlikely(res <= 0)) if (unlikely(res <= 0))
return res; return res;
return min_t(size_t, len, 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)) {
struct page *page; struct page *page;
page = first_bvec_segment(i, &len, start, maxsize); page = first_bvec_segment(i, &maxsize, start);
n = DIV_ROUND_UP(len + *start, PAGE_SIZE); n = DIV_ROUND_UP(maxsize + *start, PAGE_SIZE);
if (n > maxpages) if (n > maxpages)
n = maxpages; n = maxpages;
for (int k = 0; k < n; k++) for (int k = 0; k < n; k++)
get_page(*pages++ = page++); get_page(*pages++ = page++);
return min_t(size_t, len, n * PAGE_SIZE - *start); return min_t(size_t, maxsize, n * PAGE_SIZE - *start);
} }
if (iov_iter_is_pipe(i)) if (iov_iter_is_pipe(i))
return pipe_get_pages(i, pages, maxsize, maxpages, start); return pipe_get_pages(i, pages, maxsize, maxpages, start);
@ -1469,7 +1464,6 @@ ssize_t iov_iter_get_pages_alloc(struct iov_iter *i,
size_t *start) size_t *start)
{ {
struct page **p; struct page **p;
size_t len;
int n, res; int n, res;
if (maxsize > i->count) if (maxsize > i->count)
@ -1488,8 +1482,8 @@ ssize_t iov_iter_get_pages_alloc(struct iov_iter *i,
if (i->nofault) if (i->nofault)
gup_flags |= FOLL_NOFAULT; gup_flags |= FOLL_NOFAULT;
addr = first_iovec_segment(i, &len, start, maxsize); addr = first_iovec_segment(i, &maxsize, start);
n = DIV_ROUND_UP(len + *start, PAGE_SIZE); n = DIV_ROUND_UP(maxsize + *start, PAGE_SIZE);
p = get_pages_array(n); p = get_pages_array(n);
if (!p) if (!p)
return -ENOMEM; return -ENOMEM;
@ -1500,19 +1494,19 @@ ssize_t iov_iter_get_pages_alloc(struct iov_iter *i,
return res; return res;
} }
*pages = p; *pages = p;
return min_t(size_t, len, 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)) {
struct page *page; struct page *page;
page = first_bvec_segment(i, &len, start, maxsize); page = first_bvec_segment(i, &maxsize, start);
n = DIV_ROUND_UP(len + *start, PAGE_SIZE); n = DIV_ROUND_UP(maxsize + *start, PAGE_SIZE);
*pages = p = get_pages_array(n); *pages = p = get_pages_array(n);
if (!p) if (!p)
return -ENOMEM; return -ENOMEM;
for (int k = 0; k < n; k++) for (int k = 0; k < n; k++)
get_page(*p++ = page++); get_page(*p++ = page++);
return min_t(size_t, len, n * PAGE_SIZE - *start); return min_t(size_t, maxsize, n * PAGE_SIZE - *start);
} }
if (iov_iter_is_pipe(i)) if (iov_iter_is_pipe(i))
return pipe_get_pages_alloc(i, pages, maxsize, start); return pipe_get_pages_alloc(i, pages, maxsize, start);