xref: /openbmc/linux/io_uring/opdef.c (revision d9808ceb)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * io_uring opcode handling table
4  */
5 #include <linux/kernel.h>
6 #include <linux/errno.h>
7 #include <linux/fs.h>
8 #include <linux/file.h>
9 #include <linux/io_uring.h>
10 
11 #include "io_uring.h"
12 #include "opdef.h"
13 #include "refs.h"
14 #include "tctx.h"
15 #include "sqpoll.h"
16 #include "fdinfo.h"
17 #include "kbuf.h"
18 #include "rsrc.h"
19 
20 #include "xattr.h"
21 #include "nop.h"
22 #include "fs.h"
23 #include "splice.h"
24 #include "sync.h"
25 #include "advise.h"
26 #include "openclose.h"
27 #include "uring_cmd.h"
28 #include "epoll.h"
29 #include "statx.h"
30 #include "net.h"
31 #include "msg_ring.h"
32 #include "timeout.h"
33 #include "poll.h"
34 #include "cancel.h"
35 #include "rw.h"
36 
37 static int io_no_issue(struct io_kiocb *req, unsigned int issue_flags)
38 {
39 	WARN_ON_ONCE(1);
40 	return -ECANCELED;
41 }
42 
43 static __maybe_unused int io_eopnotsupp_prep(struct io_kiocb *kiocb,
44 					     const struct io_uring_sqe *sqe)
45 {
46 	return -EOPNOTSUPP;
47 }
48 
49 const struct io_op_def io_op_defs[] = {
50 	[IORING_OP_NOP] = {
51 		.audit_skip		= 1,
52 		.iopoll			= 1,
53 		.name			= "NOP",
54 		.prep			= io_nop_prep,
55 		.issue			= io_nop,
56 	},
57 	[IORING_OP_READV] = {
58 		.needs_file		= 1,
59 		.unbound_nonreg_file	= 1,
60 		.pollin			= 1,
61 		.buffer_select		= 1,
62 		.plug			= 1,
63 		.audit_skip		= 1,
64 		.ioprio			= 1,
65 		.iopoll			= 1,
66 		.async_size		= sizeof(struct io_async_rw),
67 		.name			= "READV",
68 		.prep			= io_prep_rw,
69 		.issue			= io_read,
70 		.prep_async		= io_readv_prep_async,
71 		.cleanup		= io_readv_writev_cleanup,
72 	},
73 	[IORING_OP_WRITEV] = {
74 		.needs_file		= 1,
75 		.hash_reg_file		= 1,
76 		.unbound_nonreg_file	= 1,
77 		.pollout		= 1,
78 		.plug			= 1,
79 		.audit_skip		= 1,
80 		.ioprio			= 1,
81 		.iopoll			= 1,
82 		.async_size		= sizeof(struct io_async_rw),
83 		.name			= "WRITEV",
84 		.prep			= io_prep_rw,
85 		.issue			= io_write,
86 		.prep_async		= io_writev_prep_async,
87 		.cleanup		= io_readv_writev_cleanup,
88 	},
89 	[IORING_OP_FSYNC] = {
90 		.needs_file		= 1,
91 		.audit_skip		= 1,
92 		.name			= "FSYNC",
93 		.prep			= io_fsync_prep,
94 		.issue			= io_fsync,
95 	},
96 	[IORING_OP_READ_FIXED] = {
97 		.needs_file		= 1,
98 		.unbound_nonreg_file	= 1,
99 		.pollin			= 1,
100 		.plug			= 1,
101 		.audit_skip		= 1,
102 		.ioprio			= 1,
103 		.iopoll			= 1,
104 		.async_size		= sizeof(struct io_async_rw),
105 		.name			= "READ_FIXED",
106 		.prep			= io_prep_rw,
107 		.issue			= io_read,
108 	},
109 	[IORING_OP_WRITE_FIXED] = {
110 		.needs_file		= 1,
111 		.hash_reg_file		= 1,
112 		.unbound_nonreg_file	= 1,
113 		.pollout		= 1,
114 		.plug			= 1,
115 		.audit_skip		= 1,
116 		.ioprio			= 1,
117 		.iopoll			= 1,
118 		.async_size		= sizeof(struct io_async_rw),
119 		.name			= "WRITE_FIXED",
120 		.prep			= io_prep_rw,
121 		.issue			= io_write,
122 	},
123 	[IORING_OP_POLL_ADD] = {
124 		.needs_file		= 1,
125 		.unbound_nonreg_file	= 1,
126 		.audit_skip		= 1,
127 		.name			= "POLL_ADD",
128 		.prep			= io_poll_add_prep,
129 		.issue			= io_poll_add,
130 	},
131 	[IORING_OP_POLL_REMOVE] = {
132 		.audit_skip		= 1,
133 		.name			= "POLL_REMOVE",
134 		.prep			= io_poll_remove_prep,
135 		.issue			= io_poll_remove,
136 	},
137 	[IORING_OP_SYNC_FILE_RANGE] = {
138 		.needs_file		= 1,
139 		.audit_skip		= 1,
140 		.name			= "SYNC_FILE_RANGE",
141 		.prep			= io_sfr_prep,
142 		.issue			= io_sync_file_range,
143 	},
144 	[IORING_OP_SENDMSG] = {
145 		.needs_file		= 1,
146 		.unbound_nonreg_file	= 1,
147 		.pollout		= 1,
148 		.ioprio			= 1,
149 		.name			= "SENDMSG",
150 #if defined(CONFIG_NET)
151 		.async_size		= sizeof(struct io_async_msghdr),
152 		.prep			= io_sendmsg_prep,
153 		.issue			= io_sendmsg,
154 		.prep_async		= io_sendmsg_prep_async,
155 		.cleanup		= io_sendmsg_recvmsg_cleanup,
156 #else
157 		.prep			= io_eopnotsupp_prep,
158 #endif
159 	},
160 	[IORING_OP_RECVMSG] = {
161 		.needs_file		= 1,
162 		.unbound_nonreg_file	= 1,
163 		.pollin			= 1,
164 		.buffer_select		= 1,
165 		.ioprio			= 1,
166 		.name			= "RECVMSG",
167 #if defined(CONFIG_NET)
168 		.async_size		= sizeof(struct io_async_msghdr),
169 		.prep			= io_recvmsg_prep,
170 		.issue			= io_recvmsg,
171 		.prep_async		= io_recvmsg_prep_async,
172 		.cleanup		= io_sendmsg_recvmsg_cleanup,
173 #else
174 		.prep			= io_eopnotsupp_prep,
175 #endif
176 	},
177 	[IORING_OP_TIMEOUT] = {
178 		.audit_skip		= 1,
179 		.async_size		= sizeof(struct io_timeout_data),
180 		.name			= "TIMEOUT",
181 		.prep			= io_timeout_prep,
182 		.issue			= io_timeout,
183 	},
184 	[IORING_OP_TIMEOUT_REMOVE] = {
185 		/* used by timeout updates' prep() */
186 		.audit_skip		= 1,
187 		.name			= "TIMEOUT_REMOVE",
188 		.prep			= io_timeout_remove_prep,
189 		.issue			= io_timeout_remove,
190 	},
191 	[IORING_OP_ACCEPT] = {
192 		.needs_file		= 1,
193 		.unbound_nonreg_file	= 1,
194 		.pollin			= 1,
195 		.poll_exclusive		= 1,
196 		.ioprio			= 1,	/* used for flags */
197 		.name			= "ACCEPT",
198 #if defined(CONFIG_NET)
199 		.prep			= io_accept_prep,
200 		.issue			= io_accept,
201 #else
202 		.prep			= io_eopnotsupp_prep,
203 #endif
204 	},
205 	[IORING_OP_ASYNC_CANCEL] = {
206 		.audit_skip		= 1,
207 		.name			= "ASYNC_CANCEL",
208 		.prep			= io_async_cancel_prep,
209 		.issue			= io_async_cancel,
210 	},
211 	[IORING_OP_LINK_TIMEOUT] = {
212 		.audit_skip		= 1,
213 		.async_size		= sizeof(struct io_timeout_data),
214 		.name			= "LINK_TIMEOUT",
215 		.prep			= io_link_timeout_prep,
216 		.issue			= io_no_issue,
217 	},
218 	[IORING_OP_CONNECT] = {
219 		.needs_file		= 1,
220 		.unbound_nonreg_file	= 1,
221 		.pollout		= 1,
222 		.name			= "CONNECT",
223 #if defined(CONFIG_NET)
224 		.async_size		= sizeof(struct io_async_connect),
225 		.prep			= io_connect_prep,
226 		.issue			= io_connect,
227 		.prep_async		= io_connect_prep_async,
228 #else
229 		.prep			= io_eopnotsupp_prep,
230 #endif
231 	},
232 	[IORING_OP_FALLOCATE] = {
233 		.needs_file		= 1,
234 		.name			= "FALLOCATE",
235 		.prep			= io_fallocate_prep,
236 		.issue			= io_fallocate,
237 	},
238 	[IORING_OP_OPENAT] = {
239 		.name			= "OPENAT",
240 		.prep			= io_openat_prep,
241 		.issue			= io_openat,
242 		.cleanup		= io_open_cleanup,
243 	},
244 	[IORING_OP_CLOSE] = {
245 		.name			= "CLOSE",
246 		.prep			= io_close_prep,
247 		.issue			= io_close,
248 	},
249 	[IORING_OP_FILES_UPDATE] = {
250 		.audit_skip		= 1,
251 		.iopoll			= 1,
252 		.name			= "FILES_UPDATE",
253 		.prep			= io_files_update_prep,
254 		.issue			= io_files_update,
255 	},
256 	[IORING_OP_STATX] = {
257 		.audit_skip		= 1,
258 		.name			= "STATX",
259 		.prep			= io_statx_prep,
260 		.issue			= io_statx,
261 		.cleanup		= io_statx_cleanup,
262 	},
263 	[IORING_OP_READ] = {
264 		.needs_file		= 1,
265 		.unbound_nonreg_file	= 1,
266 		.pollin			= 1,
267 		.buffer_select		= 1,
268 		.plug			= 1,
269 		.audit_skip		= 1,
270 		.ioprio			= 1,
271 		.iopoll			= 1,
272 		.async_size		= sizeof(struct io_async_rw),
273 		.name			= "READ",
274 		.prep			= io_prep_rw,
275 		.issue			= io_read,
276 	},
277 	[IORING_OP_WRITE] = {
278 		.needs_file		= 1,
279 		.hash_reg_file		= 1,
280 		.unbound_nonreg_file	= 1,
281 		.pollout		= 1,
282 		.plug			= 1,
283 		.audit_skip		= 1,
284 		.ioprio			= 1,
285 		.iopoll			= 1,
286 		.async_size		= sizeof(struct io_async_rw),
287 		.name			= "WRITE",
288 		.prep			= io_prep_rw,
289 		.issue			= io_write,
290 	},
291 	[IORING_OP_FADVISE] = {
292 		.needs_file		= 1,
293 		.audit_skip		= 1,
294 		.name			= "FADVISE",
295 		.prep			= io_fadvise_prep,
296 		.issue			= io_fadvise,
297 	},
298 	[IORING_OP_MADVISE] = {
299 		.name			= "MADVISE",
300 		.prep			= io_madvise_prep,
301 		.issue			= io_madvise,
302 	},
303 	[IORING_OP_SEND] = {
304 		.needs_file		= 1,
305 		.unbound_nonreg_file	= 1,
306 		.pollout		= 1,
307 		.audit_skip		= 1,
308 		.ioprio			= 1,
309 		.name			= "SEND",
310 #if defined(CONFIG_NET)
311 		.prep			= io_sendmsg_prep,
312 		.issue			= io_send,
313 #else
314 		.prep			= io_eopnotsupp_prep,
315 #endif
316 	},
317 	[IORING_OP_RECV] = {
318 		.needs_file		= 1,
319 		.unbound_nonreg_file	= 1,
320 		.pollin			= 1,
321 		.buffer_select		= 1,
322 		.audit_skip		= 1,
323 		.ioprio			= 1,
324 		.name			= "RECV",
325 #if defined(CONFIG_NET)
326 		.prep			= io_recvmsg_prep,
327 		.issue			= io_recv,
328 #else
329 		.prep			= io_eopnotsupp_prep,
330 #endif
331 	},
332 	[IORING_OP_OPENAT2] = {
333 		.name			= "OPENAT2",
334 		.prep			= io_openat2_prep,
335 		.issue			= io_openat2,
336 		.cleanup		= io_open_cleanup,
337 	},
338 	[IORING_OP_EPOLL_CTL] = {
339 		.unbound_nonreg_file	= 1,
340 		.audit_skip		= 1,
341 		.name			= "EPOLL",
342 #if defined(CONFIG_EPOLL)
343 		.prep			= io_epoll_ctl_prep,
344 		.issue			= io_epoll_ctl,
345 #else
346 		.prep			= io_eopnotsupp_prep,
347 #endif
348 	},
349 	[IORING_OP_SPLICE] = {
350 		.needs_file		= 1,
351 		.hash_reg_file		= 1,
352 		.unbound_nonreg_file	= 1,
353 		.audit_skip		= 1,
354 		.name			= "SPLICE",
355 		.prep			= io_splice_prep,
356 		.issue			= io_splice,
357 	},
358 	[IORING_OP_PROVIDE_BUFFERS] = {
359 		.audit_skip		= 1,
360 		.iopoll			= 1,
361 		.name			= "PROVIDE_BUFFERS",
362 		.prep			= io_provide_buffers_prep,
363 		.issue			= io_provide_buffers,
364 	},
365 	[IORING_OP_REMOVE_BUFFERS] = {
366 		.audit_skip		= 1,
367 		.iopoll			= 1,
368 		.name			= "REMOVE_BUFFERS",
369 		.prep			= io_remove_buffers_prep,
370 		.issue			= io_remove_buffers,
371 	},
372 	[IORING_OP_TEE] = {
373 		.needs_file		= 1,
374 		.hash_reg_file		= 1,
375 		.unbound_nonreg_file	= 1,
376 		.audit_skip		= 1,
377 		.name			= "TEE",
378 		.prep			= io_tee_prep,
379 		.issue			= io_tee,
380 	},
381 	[IORING_OP_SHUTDOWN] = {
382 		.needs_file		= 1,
383 		.name			= "SHUTDOWN",
384 #if defined(CONFIG_NET)
385 		.prep			= io_shutdown_prep,
386 		.issue			= io_shutdown,
387 #else
388 		.prep			= io_eopnotsupp_prep,
389 #endif
390 	},
391 	[IORING_OP_RENAMEAT] = {
392 		.name			= "RENAMEAT",
393 		.prep			= io_renameat_prep,
394 		.issue			= io_renameat,
395 		.cleanup		= io_renameat_cleanup,
396 	},
397 	[IORING_OP_UNLINKAT] = {
398 		.name			= "UNLINKAT",
399 		.prep			= io_unlinkat_prep,
400 		.issue			= io_unlinkat,
401 		.cleanup		= io_unlinkat_cleanup,
402 	},
403 	[IORING_OP_MKDIRAT] = {
404 		.name			= "MKDIRAT",
405 		.prep			= io_mkdirat_prep,
406 		.issue			= io_mkdirat,
407 		.cleanup		= io_mkdirat_cleanup,
408 	},
409 	[IORING_OP_SYMLINKAT] = {
410 		.name			= "SYMLINKAT",
411 		.prep			= io_symlinkat_prep,
412 		.issue			= io_symlinkat,
413 		.cleanup		= io_link_cleanup,
414 	},
415 	[IORING_OP_LINKAT] = {
416 		.name			= "LINKAT",
417 		.prep			= io_linkat_prep,
418 		.issue			= io_linkat,
419 		.cleanup		= io_link_cleanup,
420 	},
421 	[IORING_OP_MSG_RING] = {
422 		.needs_file		= 1,
423 		.iopoll			= 1,
424 		.name			= "MSG_RING",
425 		.prep			= io_msg_ring_prep,
426 		.issue			= io_msg_ring,
427 	},
428 	[IORING_OP_FSETXATTR] = {
429 		.needs_file = 1,
430 		.name			= "FSETXATTR",
431 		.prep			= io_fsetxattr_prep,
432 		.issue			= io_fsetxattr,
433 		.cleanup		= io_xattr_cleanup,
434 	},
435 	[IORING_OP_SETXATTR] = {
436 		.name			= "SETXATTR",
437 		.prep			= io_setxattr_prep,
438 		.issue			= io_setxattr,
439 		.cleanup		= io_xattr_cleanup,
440 	},
441 	[IORING_OP_FGETXATTR] = {
442 		.needs_file = 1,
443 		.name			= "FGETXATTR",
444 		.prep			= io_fgetxattr_prep,
445 		.issue			= io_fgetxattr,
446 		.cleanup		= io_xattr_cleanup,
447 	},
448 	[IORING_OP_GETXATTR] = {
449 		.name			= "GETXATTR",
450 		.prep			= io_getxattr_prep,
451 		.issue			= io_getxattr,
452 		.cleanup		= io_xattr_cleanup,
453 	},
454 	[IORING_OP_SOCKET] = {
455 		.audit_skip		= 1,
456 		.name			= "SOCKET",
457 #if defined(CONFIG_NET)
458 		.prep			= io_socket_prep,
459 		.issue			= io_socket,
460 #else
461 		.prep			= io_eopnotsupp_prep,
462 #endif
463 	},
464 	[IORING_OP_URING_CMD] = {
465 		.needs_file		= 1,
466 		.plug			= 1,
467 		.name			= "URING_CMD",
468 		.async_size		= uring_cmd_pdu_size(1),
469 		.prep			= io_uring_cmd_prep,
470 		.issue			= io_uring_cmd,
471 		.prep_async		= io_uring_cmd_prep_async,
472 	},
473 	[IORING_OP_SENDZC_NOTIF] = {
474 		.name			= "SENDZC_NOTIF",
475 		.needs_file		= 1,
476 		.unbound_nonreg_file	= 1,
477 		.pollout		= 1,
478 		.audit_skip		= 1,
479 		.ioprio			= 1,
480 		.manual_alloc		= 1,
481 #if defined(CONFIG_NET)
482 		.async_size		= sizeof(struct io_async_msghdr),
483 		.prep			= io_sendzc_prep,
484 		.issue			= io_sendzc,
485 		.prep_async		= io_sendzc_prep_async,
486 #else
487 		.prep			= io_eopnotsupp_prep,
488 #endif
489 	},
490 };
491 
492 const char *io_uring_get_opcode(u8 opcode)
493 {
494 	if (opcode < IORING_OP_LAST)
495 		return io_op_defs[opcode].name;
496 	return "INVALID";
497 }
498 
499 void __init io_uring_optable_init(void)
500 {
501 	int i;
502 
503 	BUILD_BUG_ON(ARRAY_SIZE(io_op_defs) != IORING_OP_LAST);
504 
505 	for (i = 0; i < ARRAY_SIZE(io_op_defs); i++) {
506 		BUG_ON(!io_op_defs[i].prep);
507 		if (io_op_defs[i].prep != io_eopnotsupp_prep)
508 			BUG_ON(!io_op_defs[i].issue);
509 		WARN_ON_ONCE(!io_op_defs[i].name);
510 	}
511 }
512