With other buffer types we may want to have a different way of releasing them. For example, we may want to put pages in some kind of cache or bulk put them. Add a release callback. Signed-off-by: Pavel Begunkov <asml.silence@xxxxxxxxx> --- include/linux/io_uring.h | 2 ++ io_uring/rsrc.c | 14 ++++++++++---- io_uring/rsrc.h | 5 +++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/include/linux/io_uring.h b/include/linux/io_uring.h index fddb5d52b776..e0e7df5beefc 100644 --- a/include/linux/io_uring.h +++ b/include/linux/io_uring.h @@ -26,6 +26,8 @@ struct iou_buf_desc { unsigned nr_bvecs; unsigned max_bvecs; struct bio_vec *bvec; + void (*release)(struct iou_buf_desc *); + void *private; }; struct io_uring_cmd { diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c index 0edcebb6b5cb..3799470fd45e 100644 --- a/io_uring/rsrc.c +++ b/io_uring/rsrc.c @@ -111,6 +111,8 @@ static struct io_mapped_ubuf *io_alloc_reg_buf(struct io_ring_ctx *ctx, } imu->desc.bvec = imu->bvec; imu->desc.max_bvecs = nr_bvecs; + imu->desc.private = NULL; + imu->desc.release = NULL; return imu; } @@ -169,10 +171,14 @@ static void io_buffer_unmap(struct io_ring_ctx *ctx, struct io_mapped_ubuf **slo unsigned int i; if (imu != ctx->dummy_ubuf) { - for (i = 0; i < imu->desc.nr_bvecs; i++) - unpin_user_page(imu->bvec[i].bv_page); - if (imu->acct_pages) - io_unaccount_mem(ctx, imu->acct_pages); + if (imu->desc.release) { + io_reg_buf_release(imu); + } else { + for (i = 0; i < imu->desc.nr_bvecs; i++) + unpin_user_page(imu->bvec[i].bv_page); + if (imu->acct_pages) + io_unaccount_mem(ctx, imu->acct_pages); + } io_put_reg_buf(ctx, imu); } *slot = NULL; diff --git a/io_uring/rsrc.h b/io_uring/rsrc.h index 9ac10b3d25ac..29ce9a8a2277 100644 --- a/io_uring/rsrc.h +++ b/io_uring/rsrc.h @@ -169,4 +169,9 @@ static inline void __io_unaccount_mem(struct user_struct *user, atomic_long_sub(nr_pages, &user->locked_vm); } +static inline void io_reg_buf_release(struct io_mapped_ubuf *imu) +{ + imu->desc.release(&imu->desc); +} + #endif -- 2.40.0