xref: /linux/io_uring/nop.c (revision 5832d26433f2bd0d28f8b12526e3c2fdb203507f)
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 	unsigned int	flags;
20 	__u64		extra1;
21 	__u64		extra2;
22 };
23 
24 #define NOP_FLAGS	(IORING_NOP_INJECT_RESULT | IORING_NOP_FIXED_FILE | \
25 			 IORING_NOP_FIXED_BUFFER | IORING_NOP_FILE | \
26 			 IORING_NOP_TW | IORING_NOP_CQE32)
27 
28 int io_nop_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
29 {
30 	struct io_nop *nop = io_kiocb_to_cmd(req, struct io_nop);
31 
32 	nop->flags = READ_ONCE(sqe->nop_flags);
33 	if (nop->flags & ~NOP_FLAGS)
34 		return -EINVAL;
35 
36 	if (nop->flags & IORING_NOP_INJECT_RESULT)
37 		nop->result = READ_ONCE(sqe->len);
38 	else
39 		nop->result = 0;
40 	if (nop->flags & IORING_NOP_FILE)
41 		nop->fd = READ_ONCE(sqe->fd);
42 	else
43 		nop->fd = -1;
44 	if (nop->flags & IORING_NOP_FIXED_BUFFER)
45 		req->buf_index = READ_ONCE(sqe->buf_index);
46 	if (nop->flags & IORING_NOP_CQE32) {
47 		struct io_ring_ctx *ctx = req->ctx;
48 
49 		if (!(ctx->flags & (IORING_SETUP_CQE32|IORING_SETUP_CQE_MIXED)))
50 			return -EINVAL;
51 		nop->extra1 = READ_ONCE(sqe->off);
52 		nop->extra2 = READ_ONCE(sqe->addr);
53 	}
54 	return 0;
55 }
56 
57 int io_nop(struct io_kiocb *req, unsigned int issue_flags)
58 {
59 	struct io_nop *nop = io_kiocb_to_cmd(req, struct io_nop);
60 	int ret = nop->result;
61 
62 	if (nop->flags & IORING_NOP_FILE) {
63 		if (nop->flags & IORING_NOP_FIXED_FILE) {
64 			req->file = io_file_get_fixed(req, nop->fd, issue_flags);
65 			req->flags |= REQ_F_FIXED_FILE;
66 		} else {
67 			req->file = io_file_get_normal(req, nop->fd);
68 		}
69 		if (!req->file) {
70 			ret = -EBADF;
71 			goto done;
72 		}
73 	}
74 	if (nop->flags & IORING_NOP_FIXED_BUFFER) {
75 		if (!io_find_buf_node(req, issue_flags))
76 			ret = -EFAULT;
77 	}
78 done:
79 	if (ret < 0)
80 		req_set_fail(req);
81 	if (nop->flags & IORING_NOP_CQE32)
82 		io_req_set_res32(req, nop->result, 0, nop->extra1, nop->extra2);
83 	else
84 		io_req_set_res(req, nop->result, 0);
85 	if (nop->flags & IORING_NOP_TW) {
86 		req->io_task_work.func = io_req_task_complete;
87 		io_req_task_work_add(req);
88 		return IOU_ISSUE_SKIP_COMPLETE;
89 	}
90 	return IOU_COMPLETE;
91 }
92