1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/kernel.h> 3 #include <linux/errno.h> 4 #include <linux/fs.h> 5 #include <linux/file.h> 6 #include <linux/io_uring.h> 7 8 #include <uapi/linux/io_uring.h> 9 10 #include "io_uring.h" 11 #include "rsrc.h" 12 #include "nop.h" 13 14 struct io_nop { 15 /* NOTE: kiocb has the file as the first member, so don't do it here */ 16 struct file *file; 17 int result; 18 int fd; 19 int buffer; 20 unsigned int flags; 21 }; 22 23 #define NOP_FLAGS (IORING_NOP_INJECT_RESULT | IORING_NOP_FIXED_FILE | \ 24 IORING_NOP_FIXED_BUFFER | IORING_NOP_FILE) 25 26 int io_nop_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 27 { 28 struct io_nop *nop = io_kiocb_to_cmd(req, struct io_nop); 29 30 nop->flags = READ_ONCE(sqe->nop_flags); 31 if (nop->flags & ~NOP_FLAGS) 32 return -EINVAL; 33 34 if (nop->flags & IORING_NOP_INJECT_RESULT) 35 nop->result = READ_ONCE(sqe->len); 36 else 37 nop->result = 0; 38 if (nop->flags & IORING_NOP_FIXED_FILE) 39 nop->fd = READ_ONCE(sqe->fd); 40 if (nop->flags & IORING_NOP_FIXED_BUFFER) 41 nop->buffer = READ_ONCE(sqe->buf_index); 42 return 0; 43 } 44 45 int io_nop(struct io_kiocb *req, unsigned int issue_flags) 46 { 47 struct io_nop *nop = io_kiocb_to_cmd(req, struct io_nop); 48 int ret = nop->result; 49 50 if (nop->flags & IORING_NOP_FILE) { 51 if (nop->flags & IORING_NOP_FIXED_FILE) { 52 req->file = io_file_get_fixed(req, nop->fd, issue_flags); 53 req->flags |= REQ_F_FIXED_FILE; 54 } else { 55 req->file = io_file_get_normal(req, nop->fd); 56 } 57 if (!req->file) { 58 ret = -EBADF; 59 goto done; 60 } 61 } 62 if (nop->flags & IORING_NOP_FIXED_BUFFER) { 63 struct io_ring_ctx *ctx = req->ctx; 64 struct io_rsrc_node *node; 65 66 ret = -EFAULT; 67 io_ring_submit_lock(ctx, issue_flags); 68 node = io_rsrc_node_lookup(&ctx->buf_table, nop->buffer); 69 if (node) { 70 io_req_assign_buf_node(req, node); 71 ret = 0; 72 } 73 io_ring_submit_unlock(ctx, issue_flags); 74 } 75 done: 76 if (ret < 0) 77 req_set_fail(req); 78 io_req_set_res(req, nop->result, 0); 79 return IOU_OK; 80 } 81