Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

io_uring: add support for IORING_OP_PIPE

This works just like pipe2(2), except it also supports fixed file
descriptors. Used in a similar fashion as for other fd instantiating
opcodes (like accept, socket, open, etc), where sqe->file_slot is set
appropriately if two direct descriptors are desired rather than a set
of normal file descriptors.

sqe->addr must be set to a pointer to an array of 2 integers, which
is where the fixed/normal file descriptors are copied to.

sqe->pipe_flags contains flags, same as what is allowed for pipe2(2).

Future expansion of per-op private flags can go in sqe->ioprio,
like we do for other opcodes that take both a "syscall" flag set and
an io_uring opcode specific flag set.

Signed-off-by: Jens Axboe <axboe@kernel.dk>

+145
+2
include/uapi/linux/io_uring.h
··· 73 73 __u32 futex_flags; 74 74 __u32 install_fd_flags; 75 75 __u32 nop_flags; 76 + __u32 pipe_flags; 76 77 }; 77 78 __u64 user_data; /* data to be passed back at completion time */ 78 79 /* pack this to avoid bogus arm OABI complaints */ ··· 284 283 IORING_OP_EPOLL_WAIT, 285 284 IORING_OP_READV_FIXED, 286 285 IORING_OP_WRITEV_FIXED, 286 + IORING_OP_PIPE, 287 287 288 288 /* this goes last, obviously */ 289 289 IORING_OP_LAST,
+7
io_uring/opdef.c
··· 569 569 .prep = io_prep_writev_fixed, 570 570 .issue = io_write, 571 571 }, 572 + [IORING_OP_PIPE] = { 573 + .prep = io_pipe_prep, 574 + .issue = io_pipe, 575 + }, 572 576 }; 573 577 574 578 const struct io_cold_def io_cold_defs[] = { ··· 818 814 .name = "WRITEV_FIXED", 819 815 .cleanup = io_readv_writev_cleanup, 820 816 .fail = io_rw_fail, 817 + }, 818 + [IORING_OP_PIPE] = { 819 + .name = "PIPE", 821 820 }, 822 821 }; 823 822
+133
io_uring/openclose.c
··· 6 6 #include <linux/fdtable.h> 7 7 #include <linux/fsnotify.h> 8 8 #include <linux/namei.h> 9 + #include <linux/pipe_fs_i.h> 10 + #include <linux/watch_queue.h> 9 11 #include <linux/io_uring.h> 10 12 11 13 #include <uapi/linux/io_uring.h> ··· 303 301 req_set_fail(req); 304 302 io_req_set_res(req, ret, 0); 305 303 return IOU_OK; 304 + } 305 + 306 + struct io_pipe { 307 + struct file *file; 308 + int __user *fds; 309 + int flags; 310 + int file_slot; 311 + unsigned long nofile; 312 + }; 313 + 314 + int io_pipe_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 315 + { 316 + struct io_pipe *p = io_kiocb_to_cmd(req, struct io_pipe); 317 + 318 + if (sqe->fd || sqe->off || sqe->addr3) 319 + return -EINVAL; 320 + 321 + p->fds = u64_to_user_ptr(READ_ONCE(sqe->addr)); 322 + p->flags = READ_ONCE(sqe->pipe_flags); 323 + if (p->flags & ~(O_CLOEXEC | O_NONBLOCK | O_DIRECT | O_NOTIFICATION_PIPE)) 324 + return -EINVAL; 325 + 326 + p->file_slot = READ_ONCE(sqe->file_index); 327 + p->nofile = rlimit(RLIMIT_NOFILE); 328 + return 0; 329 + } 330 + 331 + static int io_pipe_fixed(struct io_kiocb *req, struct file **files, 332 + unsigned int issue_flags) 333 + { 334 + struct io_pipe *p = io_kiocb_to_cmd(req, struct io_pipe); 335 + struct io_ring_ctx *ctx = req->ctx; 336 + int ret, fds[2] = { -1, -1 }; 337 + int slot = p->file_slot; 338 + 339 + if (p->flags & O_CLOEXEC) 340 + return -EINVAL; 341 + 342 + io_ring_submit_lock(ctx, issue_flags); 343 + 344 + ret = __io_fixed_fd_install(ctx, files[0], slot); 345 + if (ret < 0) 346 + goto err; 347 + fds[0] = ret; 348 + files[0] = NULL; 349 + 350 + /* 351 + * If a specific slot is given, next one will be used for 352 + * the write side. 353 + */ 354 + if (slot != IORING_FILE_INDEX_ALLOC) 355 + slot++; 356 + 357 + ret = __io_fixed_fd_install(ctx, files[1], slot); 358 + if (ret < 0) 359 + goto err; 360 + fds[1] = ret; 361 + files[1] = NULL; 362 + 363 + io_ring_submit_unlock(ctx, issue_flags); 364 + 365 + if (!copy_to_user(p->fds, fds, sizeof(fds))) 366 + return 0; 367 + 368 + ret = -EFAULT; 369 + io_ring_submit_lock(ctx, issue_flags); 370 + err: 371 + if (fds[0] != -1) 372 + io_fixed_fd_remove(ctx, fds[0]); 373 + if (fds[1] != -1) 374 + io_fixed_fd_remove(ctx, fds[1]); 375 + io_ring_submit_unlock(ctx, issue_flags); 376 + return ret; 377 + } 378 + 379 + static int io_pipe_fd(struct io_kiocb *req, struct file **files) 380 + { 381 + struct io_pipe *p = io_kiocb_to_cmd(req, struct io_pipe); 382 + int ret, fds[2] = { -1, -1 }; 383 + 384 + ret = __get_unused_fd_flags(p->flags, p->nofile); 385 + if (ret < 0) 386 + goto err; 387 + fds[0] = ret; 388 + 389 + ret = __get_unused_fd_flags(p->flags, p->nofile); 390 + if (ret < 0) 391 + goto err; 392 + fds[1] = ret; 393 + 394 + if (!copy_to_user(p->fds, fds, sizeof(fds))) { 395 + fd_install(fds[0], files[0]); 396 + fd_install(fds[1], files[1]); 397 + return 0; 398 + } 399 + ret = -EFAULT; 400 + err: 401 + if (fds[0] != -1) 402 + put_unused_fd(fds[0]); 403 + if (fds[1] != -1) 404 + put_unused_fd(fds[1]); 405 + return ret; 406 + } 407 + 408 + int io_pipe(struct io_kiocb *req, unsigned int issue_flags) 409 + { 410 + struct io_pipe *p = io_kiocb_to_cmd(req, struct io_pipe); 411 + struct file *files[2]; 412 + int ret; 413 + 414 + ret = create_pipe_files(files, p->flags); 415 + if (ret) 416 + return ret; 417 + files[0]->f_mode |= FMODE_NOWAIT; 418 + files[1]->f_mode |= FMODE_NOWAIT; 419 + 420 + if (!!p->file_slot) 421 + ret = io_pipe_fixed(req, files, issue_flags); 422 + else 423 + ret = io_pipe_fd(req, files); 424 + 425 + io_req_set_res(req, ret, 0); 426 + if (!ret) 427 + return IOU_OK; 428 + 429 + req_set_fail(req); 430 + if (files[0]) 431 + fput(files[0]); 432 + if (files[1]) 433 + fput(files[1]); 434 + return ret; 306 435 }
+3
io_uring/openclose.h
··· 13 13 int io_close_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe); 14 14 int io_close(struct io_kiocb *req, unsigned int issue_flags); 15 15 16 + int io_pipe_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe); 17 + int io_pipe(struct io_kiocb *req, unsigned int issue_flags); 18 + 16 19 int io_install_fixed_fd_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe); 17 20 int io_install_fixed_fd(struct io_kiocb *req, unsigned int issue_flags);