Add two new helpers, io_uring_cmd_fixed_index_get() and io_uring_cmd_fixed_index_put(). io_uring_cmd_fixed_index_get() constructs an iter for a fixed buffer at a given index and acquires a refcount on the underlying node. io_uring_cmd_fixed_index_put() decrements this refcount. The caller is responsible for ensuring io_uring_cmd_fixed_index_put() is properly called for releasing the refcount after it is done using the iter it obtained through io_uring_cmd_fixed_index_get(). This is a preparatory patch needed for fuse-over-io-uring support, as the metadata for fuse requests will be stored at the last index, which will be different from the buf index set on the sqe. Signed-off-by: Joanne Koong --- include/linux/io_uring/cmd.h | 20 +++++++++++ io_uring/rsrc.c | 65 ++++++++++++++++++++++++++++++++++++ io_uring/rsrc.h | 5 +++ io_uring/uring_cmd.c | 21 ++++++++++++ 4 files changed, 111 insertions(+) diff --git a/include/linux/io_uring/cmd.h b/include/linux/io_uring/cmd.h index 7169a2a9a744..2988592e045c 100644 --- a/include/linux/io_uring/cmd.h +++ b/include/linux/io_uring/cmd.h @@ -44,6 +44,12 @@ int io_uring_cmd_import_fixed_vec(struct io_uring_cmd *ioucmd, size_t uvec_segs, int ddir, struct iov_iter *iter, unsigned issue_flags); +int io_uring_cmd_fixed_index_get(struct io_uring_cmd *ioucmd, u16 buf_index, + unsigned int off, size_t len, int ddir, + struct iov_iter *iter, + unsigned int issue_flags); +int io_uring_cmd_fixed_index_put(struct io_uring_cmd *ioucmd, u16 buf_index, + unsigned int issue_flags); /* * Completes the request, i.e. posts an io_uring CQE and deallocates @ioucmd @@ -109,6 +115,20 @@ static inline int io_uring_cmd_import_fixed_vec(struct io_uring_cmd *ioucmd, { return -EOPNOTSUPP; } +static inline int io_uring_cmd_fixed_index_get(struct io_uring_cmd *ioucmd, + u16 buf_index, unsigned int off, + size_t len, int ddir, + struct iov_iter *iter, + unsigned int issue_flags) +{ + return -EOPNOTSUPP; +} +static inline int io_uring_cmd_fixed_index_put(struct io_uring_cmd *ioucmd, + u16 buf_index, + unsigned int issue_flags) +{ + return -EOPNOTSUPP; +} static inline void __io_uring_cmd_done(struct io_uring_cmd *cmd, s32 ret, u64 ret2, unsigned issue_flags, bool is_cqe32) { diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c index a63474b331bf..a141aaeb099d 100644 --- a/io_uring/rsrc.c +++ b/io_uring/rsrc.c @@ -1151,6 +1151,71 @@ int io_import_reg_buf(struct io_kiocb *req, struct iov_iter *iter, return io_import_fixed(ddir, iter, node->buf, buf_addr, len); } +int io_reg_buf_index_get(struct io_kiocb *req, struct iov_iter *iter, + u16 buf_index, unsigned int off, size_t len, + int ddir, unsigned issue_flags) +{ + struct io_ring_ctx *ctx = req->ctx; + struct io_rsrc_node *node; + struct io_mapped_ubuf *imu; + u64 addr; + int err; + + io_ring_submit_lock(ctx, issue_flags); + + node = io_rsrc_node_lookup(&ctx->buf_table, buf_index); + if (!node) { + io_ring_submit_unlock(ctx, issue_flags); + return -EINVAL; + } + + node->refs++; + + io_ring_submit_unlock(ctx, issue_flags); + + imu = node->buf; + if (!imu) { + err = -EFAULT; + goto error; + } + + if (check_add_overflow(imu->ubuf, off, &addr)) { + err = -EINVAL; + goto error; + } + + err = io_import_fixed(ddir, iter, imu, addr, len); + if (err) + goto error; + + return 0; + +error: + io_reg_buf_index_put(req, buf_index, issue_flags); + return err; +} + +int io_reg_buf_index_put(struct io_kiocb *req, u16 buf_index, + unsigned issue_flags) +{ + struct io_ring_ctx *ctx = req->ctx; + struct io_rsrc_node *node; + + io_ring_submit_lock(ctx, issue_flags); + + node = io_rsrc_node_lookup(&ctx->buf_table, buf_index); + if (WARN_ON_ONCE(!node)) { + io_ring_submit_unlock(ctx, issue_flags); + return -EFAULT; + } + + io_put_rsrc_node(ctx, node); + + io_ring_submit_unlock(ctx, issue_flags); + + return 0; +} + /* Lock two rings at once. The rings must be different! */ static void lock_two_rings(struct io_ring_ctx *ctx1, struct io_ring_ctx *ctx2) { diff --git a/io_uring/rsrc.h b/io_uring/rsrc.h index d603f6a47f5e..16f4bab9582b 100644 --- a/io_uring/rsrc.h +++ b/io_uring/rsrc.h @@ -64,6 +64,11 @@ struct io_rsrc_node *io_find_buf_node(struct io_kiocb *req, int io_import_reg_buf(struct io_kiocb *req, struct iov_iter *iter, u64 buf_addr, size_t len, int ddir, unsigned issue_flags); +int io_reg_buf_index_get(struct io_kiocb *req, struct iov_iter *iter, + u16 buf_index, unsigned int off, size_t len, + int ddir, unsigned issue_flags); +int io_reg_buf_index_put(struct io_kiocb *req, u16 buf_index, + unsigned issue_flags); int io_import_reg_vec(int ddir, struct iov_iter *iter, struct io_kiocb *req, struct iou_vec *vec, unsigned nr_iovs, unsigned issue_flags); diff --git a/io_uring/uring_cmd.c b/io_uring/uring_cmd.c index b6b675010bfd..ee95d1102505 100644 --- a/io_uring/uring_cmd.c +++ b/io_uring/uring_cmd.c @@ -314,6 +314,27 @@ int io_uring_cmd_import_fixed_vec(struct io_uring_cmd *ioucmd, } EXPORT_SYMBOL_GPL(io_uring_cmd_import_fixed_vec); +int io_uring_cmd_fixed_index_get(struct io_uring_cmd *ioucmd, u16 buf_index, + unsigned int off, size_t len, int ddir, + struct iov_iter *iter, + unsigned int issue_flags) +{ + struct io_kiocb *req = cmd_to_io_kiocb(ioucmd); + + return io_reg_buf_index_get(req, iter, buf_index, off, len, ddir, + issue_flags); +} +EXPORT_SYMBOL_GPL(io_uring_cmd_fixed_index_get); + +int io_uring_cmd_fixed_index_put(struct io_uring_cmd *ioucmd, u16 buf_index, + unsigned int issue_flags) +{ + struct io_kiocb *req = cmd_to_io_kiocb(ioucmd); + + return io_reg_buf_index_put(req, buf_index, issue_flags); +} +EXPORT_SYMBOL_GPL(io_uring_cmd_fixed_index_put); + void io_uring_cmd_issue_blocking(struct io_uring_cmd *ioucmd) { struct io_kiocb *req = cmd_to_io_kiocb(ioucmd); -- 2.47.3