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_SEND_ZC] = { 474 .name = "SEND_ZC", 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 .cleanup = io_sendzc_cleanup, 487 #else 488 .prep = io_eopnotsupp_prep, 489 #endif 490 }, 491 }; 492 493 const char *io_uring_get_opcode(u8 opcode) 494 { 495 if (opcode < IORING_OP_LAST) 496 return io_op_defs[opcode].name; 497 return "INVALID"; 498 } 499 500 void __init io_uring_optable_init(void) 501 { 502 int i; 503 504 BUILD_BUG_ON(ARRAY_SIZE(io_op_defs) != IORING_OP_LAST); 505 506 for (i = 0; i < ARRAY_SIZE(io_op_defs); i++) { 507 BUG_ON(!io_op_defs[i].prep); 508 if (io_op_defs[i].prep != io_eopnotsupp_prep) 509 BUG_ON(!io_op_defs[i].issue); 510 WARN_ON_ONCE(!io_op_defs[i].name); 511 } 512 } 513