Skip to content

Commit d8c2237

Browse files
committed
io_uring: add io_pin_pages() helper
Abstract this out from io_sqe_buffer_register() so we can use it elsewhere too without duplicating this code. No intended functional changes in this patch. Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 3d20024 commit d8c2237

File tree

1 file changed

+50
-27
lines changed

1 file changed

+50
-27
lines changed

fs/io_uring.c

Lines changed: 50 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9845,30 +9845,18 @@ static int io_buffer_account_pin(struct io_ring_ctx *ctx, struct page **pages,
98459845
return ret;
98469846
}
98479847

9848-
static int io_sqe_buffer_register(struct io_ring_ctx *ctx, struct iovec *iov,
9849-
struct io_mapped_ubuf **pimu,
9850-
struct page **last_hpage)
9848+
static struct page **io_pin_pages(unsigned long ubuf, unsigned long len,
9849+
int *npages)
98519850
{
9852-
struct io_mapped_ubuf *imu = NULL;
9851+
unsigned long start, end, nr_pages;
98539852
struct vm_area_struct **vmas = NULL;
98549853
struct page **pages = NULL;
9855-
unsigned long off, start, end, ubuf;
9856-
size_t size;
9857-
int ret, pret, nr_pages, i;
9858-
9859-
if (!iov->iov_base) {
9860-
*pimu = ctx->dummy_ubuf;
9861-
return 0;
9862-
}
9854+
int i, pret, ret = -ENOMEM;
98639855

9864-
ubuf = (unsigned long) iov->iov_base;
9865-
end = (ubuf + iov->iov_len + PAGE_SIZE - 1) >> PAGE_SHIFT;
9856+
end = (ubuf + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
98669857
start = ubuf >> PAGE_SHIFT;
98679858
nr_pages = end - start;
98689859

9869-
*pimu = NULL;
9870-
ret = -ENOMEM;
9871-
98729860
pages = kvmalloc_array(nr_pages, sizeof(struct page *), GFP_KERNEL);
98739861
if (!pages)
98749862
goto done;
@@ -9878,10 +9866,6 @@ static int io_sqe_buffer_register(struct io_ring_ctx *ctx, struct iovec *iov,
98789866
if (!vmas)
98799867
goto done;
98809868

9881-
imu = kvmalloc(struct_size(imu, bvec, nr_pages), GFP_KERNEL);
9882-
if (!imu)
9883-
goto done;
9884-
98859869
ret = 0;
98869870
mmap_read_lock(current->mm);
98879871
pret = pin_user_pages(ubuf, nr_pages, FOLL_WRITE | FOLL_LONGTERM,
@@ -9899,6 +9883,7 @@ static int io_sqe_buffer_register(struct io_ring_ctx *ctx, struct iovec *iov,
98999883
break;
99009884
}
99019885
}
9886+
*npages = nr_pages;
99029887
} else {
99039888
ret = pret < 0 ? pret : -EFAULT;
99049889
}
@@ -9912,14 +9897,53 @@ static int io_sqe_buffer_register(struct io_ring_ctx *ctx, struct iovec *iov,
99129897
unpin_user_pages(pages, pret);
99139898
goto done;
99149899
}
9900+
ret = 0;
9901+
done:
9902+
kvfree(vmas);
9903+
if (ret < 0) {
9904+
kvfree(pages);
9905+
pages = ERR_PTR(ret);
9906+
}
9907+
return pages;
9908+
}
99159909

9916-
ret = io_buffer_account_pin(ctx, pages, pret, imu, last_hpage);
9910+
static int io_sqe_buffer_register(struct io_ring_ctx *ctx, struct iovec *iov,
9911+
struct io_mapped_ubuf **pimu,
9912+
struct page **last_hpage)
9913+
{
9914+
struct io_mapped_ubuf *imu = NULL;
9915+
struct page **pages = NULL;
9916+
unsigned long off;
9917+
size_t size;
9918+
int ret, nr_pages, i;
9919+
9920+
if (!iov->iov_base) {
9921+
*pimu = ctx->dummy_ubuf;
9922+
return 0;
9923+
}
9924+
9925+
*pimu = NULL;
9926+
ret = -ENOMEM;
9927+
9928+
pages = io_pin_pages((unsigned long) iov->iov_base, iov->iov_len,
9929+
&nr_pages);
9930+
if (IS_ERR(pages)) {
9931+
ret = PTR_ERR(pages);
9932+
pages = NULL;
9933+
goto done;
9934+
}
9935+
9936+
imu = kvmalloc(struct_size(imu, bvec, nr_pages), GFP_KERNEL);
9937+
if (!imu)
9938+
goto done;
9939+
9940+
ret = io_buffer_account_pin(ctx, pages, nr_pages, imu, last_hpage);
99179941
if (ret) {
9918-
unpin_user_pages(pages, pret);
9942+
unpin_user_pages(pages, nr_pages);
99199943
goto done;
99209944
}
99219945

9922-
off = ubuf & ~PAGE_MASK;
9946+
off = (unsigned long) iov->iov_base & ~PAGE_MASK;
99239947
size = iov->iov_len;
99249948
for (i = 0; i < nr_pages; i++) {
99259949
size_t vec_len;
@@ -9932,16 +9956,15 @@ static int io_sqe_buffer_register(struct io_ring_ctx *ctx, struct iovec *iov,
99329956
size -= vec_len;
99339957
}
99349958
/* store original address for later verification */
9935-
imu->ubuf = ubuf;
9936-
imu->ubuf_end = ubuf + iov->iov_len;
9959+
imu->ubuf = (unsigned long) iov->iov_base;
9960+
imu->ubuf_end = imu->ubuf + iov->iov_len;
99379961
imu->nr_bvecs = nr_pages;
99389962
*pimu = imu;
99399963
ret = 0;
99409964
done:
99419965
if (ret)
99429966
kvfree(imu);
99439967
kvfree(pages);
9944-
kvfree(vmas);
99459968
return ret;
99469969
}
99479970

0 commit comments

Comments
 (0)