Loading include/uapi/linux/io_uring.h +3 −0 Original line number Diff line number Diff line Loading @@ -416,6 +416,9 @@ enum io_uring_msg_ring_flags { * IORING_NOP_INJECT_RESULT Inject result from sqe->result */ #define IORING_NOP_INJECT_RESULT (1U << 0) #define IORING_NOP_FILE (1U << 1) #define IORING_NOP_FIXED_FILE (1U << 2) #define IORING_NOP_FIXED_BUFFER (1U << 3) /* * IO completion data structure (Completion Queue Entry) Loading io_uring/nop.c +44 −5 Original line number Diff line number Diff line Loading @@ -8,35 +8,74 @@ #include <uapi/linux/io_uring.h> #include "io_uring.h" #include "rsrc.h" #include "nop.h" struct io_nop { /* NOTE: kiocb has the file as the first member, so don't do it here */ struct file *file; int result; int fd; int buffer; unsigned int flags; }; #define NOP_FLAGS (IORING_NOP_INJECT_RESULT | IORING_NOP_FIXED_FILE | \ IORING_NOP_FIXED_BUFFER | IORING_NOP_FILE) int io_nop_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) { unsigned int flags; struct io_nop *nop = io_kiocb_to_cmd(req, struct io_nop); flags = READ_ONCE(sqe->nop_flags); if (flags & ~IORING_NOP_INJECT_RESULT) nop->flags = READ_ONCE(sqe->nop_flags); if (nop->flags & ~NOP_FLAGS) return -EINVAL; if (flags & IORING_NOP_INJECT_RESULT) if (nop->flags & IORING_NOP_INJECT_RESULT) nop->result = READ_ONCE(sqe->len); else nop->result = 0; if (nop->flags & IORING_NOP_FIXED_FILE) nop->fd = READ_ONCE(sqe->fd); if (nop->flags & IORING_NOP_FIXED_BUFFER) nop->buffer = READ_ONCE(sqe->buf_index); return 0; } int io_nop(struct io_kiocb *req, unsigned int issue_flags) { struct io_nop *nop = io_kiocb_to_cmd(req, struct io_nop); int ret = nop->result; if (nop->result < 0) if (nop->flags & IORING_NOP_FILE) { if (nop->flags & IORING_NOP_FIXED_FILE) { req->file = io_file_get_fixed(req, nop->fd, issue_flags); req->flags |= REQ_F_FIXED_FILE; } else { req->file = io_file_get_normal(req, nop->fd); } if (!req->file) { ret = -EBADF; goto done; } } if (nop->flags & IORING_NOP_FIXED_BUFFER) { struct io_ring_ctx *ctx = req->ctx; struct io_mapped_ubuf *imu; int idx; ret = -EFAULT; io_ring_submit_lock(ctx, issue_flags); if (nop->buffer < ctx->nr_user_bufs) { idx = array_index_nospec(nop->buffer, ctx->nr_user_bufs); imu = READ_ONCE(ctx->user_bufs[idx]); io_req_set_rsrc_node(req, ctx); ret = 0; } io_ring_submit_unlock(ctx, issue_flags); } done: if (ret < 0) req_set_fail(req); io_req_set_res(req, nop->result, 0); return IOU_OK; Loading Loading
include/uapi/linux/io_uring.h +3 −0 Original line number Diff line number Diff line Loading @@ -416,6 +416,9 @@ enum io_uring_msg_ring_flags { * IORING_NOP_INJECT_RESULT Inject result from sqe->result */ #define IORING_NOP_INJECT_RESULT (1U << 0) #define IORING_NOP_FILE (1U << 1) #define IORING_NOP_FIXED_FILE (1U << 2) #define IORING_NOP_FIXED_BUFFER (1U << 3) /* * IO completion data structure (Completion Queue Entry) Loading
io_uring/nop.c +44 −5 Original line number Diff line number Diff line Loading @@ -8,35 +8,74 @@ #include <uapi/linux/io_uring.h> #include "io_uring.h" #include "rsrc.h" #include "nop.h" struct io_nop { /* NOTE: kiocb has the file as the first member, so don't do it here */ struct file *file; int result; int fd; int buffer; unsigned int flags; }; #define NOP_FLAGS (IORING_NOP_INJECT_RESULT | IORING_NOP_FIXED_FILE | \ IORING_NOP_FIXED_BUFFER | IORING_NOP_FILE) int io_nop_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) { unsigned int flags; struct io_nop *nop = io_kiocb_to_cmd(req, struct io_nop); flags = READ_ONCE(sqe->nop_flags); if (flags & ~IORING_NOP_INJECT_RESULT) nop->flags = READ_ONCE(sqe->nop_flags); if (nop->flags & ~NOP_FLAGS) return -EINVAL; if (flags & IORING_NOP_INJECT_RESULT) if (nop->flags & IORING_NOP_INJECT_RESULT) nop->result = READ_ONCE(sqe->len); else nop->result = 0; if (nop->flags & IORING_NOP_FIXED_FILE) nop->fd = READ_ONCE(sqe->fd); if (nop->flags & IORING_NOP_FIXED_BUFFER) nop->buffer = READ_ONCE(sqe->buf_index); return 0; } int io_nop(struct io_kiocb *req, unsigned int issue_flags) { struct io_nop *nop = io_kiocb_to_cmd(req, struct io_nop); int ret = nop->result; if (nop->result < 0) if (nop->flags & IORING_NOP_FILE) { if (nop->flags & IORING_NOP_FIXED_FILE) { req->file = io_file_get_fixed(req, nop->fd, issue_flags); req->flags |= REQ_F_FIXED_FILE; } else { req->file = io_file_get_normal(req, nop->fd); } if (!req->file) { ret = -EBADF; goto done; } } if (nop->flags & IORING_NOP_FIXED_BUFFER) { struct io_ring_ctx *ctx = req->ctx; struct io_mapped_ubuf *imu; int idx; ret = -EFAULT; io_ring_submit_lock(ctx, issue_flags); if (nop->buffer < ctx->nr_user_bufs) { idx = array_index_nospec(nop->buffer, ctx->nr_user_bufs); imu = READ_ONCE(ctx->user_bufs[idx]); io_req_set_rsrc_node(req, ctx); ret = 0; } io_ring_submit_unlock(ctx, issue_flags); } done: if (ret < 0) req_set_fail(req); io_req_set_res(req, nop->result, 0); return IOU_OK; Loading