This adds IORING_OP_EPOLL_CTL, which can perform the same work as the epoll_ctl(2) system call.
Unified · Split
| @@ -74,6 +74,7 @@ · 73 unmodified lines | ||
| 74 | 74 | #include <linux/namei.h> |
| 75 | 75 | #include <linux/fsnotify.h> |
| 76 | 76 | #include <linux/fadvise.h> |
| 77 | +#include <linux/eventpoll.h> | |
| 77 | 78 | |
| 78 | 79 | #define CREATE_TRACE_POINTS |
| 79 | 80 | #include <trace/events/io_uring.h> |
| @@ -423,6 +424,14 @@ struct io_madvise { · 343 unmodified lines | ||
| 423 | 424 | u32 advice; |
| 424 | 425 | }; |
| 425 | 426 | |
| 427 | +struct io_epoll { | |
| 428 | + struct file *file; | |
| 429 | + int epfd; | |
| 430 | + int op; | |
| 431 | + int fd; | |
| 432 | + struct epoll_event event; | |
| 433 | +}; | |
| 434 | + | |
| 426 | 435 | struct io_async_connect { |
| 427 | 436 | struct sockaddr_storage address; |
| 428 | 437 | }; |
| @@ -536,6 +545,7 @@ struct io_kiocb { · 107 unmodified lines | ||
| 536 | 545 | struct io_files_update files_update; |
| 537 | 546 | struct io_fadvise fadvise; |
| 538 | 547 | struct io_madvise madvise; |
| 548 | + struct io_epoll epoll; | |
| 539 | 549 | }; |
| 540 | 550 | |
| 541 | 551 | struct io_async_ctx *io; |
| @@ -728,6 +738,10 @@ static const struct io_op_def io_op_defs[] = { · 186 unmodified lines | ||
| 728 | 738 | .fd_non_neg = 1, |
| 729 | 739 | .file_table = 1, |
| 730 | 740 | }, |
| 741 | + [IORING_OP_EPOLL_CTL] = { | |
| 742 | + .unbound_nonreg_file = 1, | |
| 743 | + .file_table = 1, | |
| 744 | + }, | |
| 731 | 745 | }; |
| 732 | 746 | |
| 733 | 747 | static void io_wq_submit_work(struct io_wq_work **workptr); |
| @@ -2611,6 +2625,52 @@ static int io_openat(struct io_kiocb *req, struct io_kiocb **nxt, · 1877 unmodified lines | ||
| 2611 | 2625 | return io_openat2(req, nxt, force_nonblock); |
| 2612 | 2626 | } |
| 2613 | 2627 | |
| 2628 | +static int io_epoll_ctl_prep(struct io_kiocb *req, | |
| 2629 | + const struct io_uring_sqe *sqe) | |
| 2630 | +{ | |
| 2631 | +#if defined(CONFIG_EPOLL) | |
| 2632 | + if (sqe->ioprio || sqe->buf_index) | |
| 2633 | + return -EINVAL; | |
| 2634 | + | |
| 2635 | + req->epoll.epfd = READ_ONCE(sqe->fd); | |
| 2636 | + req->epoll.op = READ_ONCE(sqe->len); | |
| 2637 | + req->epoll.fd = READ_ONCE(sqe->off); | |
| 2638 | + | |
| 2639 | + if (ep_op_has_event(req->epoll.op)) { | |
| 2640 | + struct epoll_event __user *ev; | |
| 2641 | + | |
| 2642 | + ev = u64_to_user_ptr(READ_ONCE(sqe->addr)); | |
| 2643 | + if (copy_from_user(&req->epoll.event, ev, sizeof(*ev))) | |
| 2644 | + return -EFAULT; | |
| 2645 | + } | |
| 2646 | + | |
| 2647 | + return 0; | |
| 2648 | +#else | |
| 2649 | + return -EOPNOTSUPP; | |
| 2650 | +#endif | |
| 2651 | +} | |
| 2652 | + | |
| 2653 | +static int io_epoll_ctl(struct io_kiocb *req, struct io_kiocb **nxt, | |
| 2654 | + bool force_nonblock) | |
| 2655 | +{ | |
| 2656 | +#if defined(CONFIG_EPOLL) | |
| 2657 | + struct io_epoll *ie = &req->epoll; | |
| 2658 | + int ret; | |
| 2659 | + | |
| 2660 | + ret = do_epoll_ctl(ie->epfd, ie->op, ie->fd, &ie->event, force_nonblock); | |
| 2661 | + if (force_nonblock && ret == -EAGAIN) | |
| 2662 | + return -EAGAIN; | |
| 2663 | + | |
| 2664 | + if (ret < 0) | |
| 2665 | + req_set_fail_links(req); | |
| 2666 | + io_cqring_add_event(req, ret); | |
| 2667 | + io_put_req_find_next(req, nxt); | |
| 2668 | + return 0; | |
| 2669 | +#else | |
| 2670 | + return -EOPNOTSUPP; | |
| 2671 | +#endif | |
| 2672 | +} | |
| 2673 | + | |
| 2614 | 2674 | static int io_madvise_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) |
| 2615 | 2675 | { |
| 2616 | 2676 | #if defined(CONFIG_ADVISE_SYSCALLS) && defined(CONFIG_MMU) |
| @@ -4075,6 +4135,9 @@ static int io_req_defer_prep(struct io_kiocb *req, · 1458 unmodified lines | ||
| 4075 | 4135 | case IORING_OP_OPENAT2: |
| 4076 | 4136 | ret = io_openat2_prep(req, sqe); |
| 4077 | 4137 | break; |
| 4138 | + case IORING_OP_EPOLL_CTL: | |
| 4139 | + ret = io_epoll_ctl_prep(req, sqe); | |
| 4140 | + break; | |
| 4078 | 4141 | default: |
| 4079 | 4142 | printk_once(KERN_WARNING "io_uring: unhandled opcode %d\n", |
| 4080 | 4143 | req->opcode); |
| @@ -4303,6 +4366,14 @@ static int io_issue_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe, · 222 unmodified lines | ||
| 4303 | 4366 | } |
| 4304 | 4367 | ret = io_openat2(req, nxt, force_nonblock); |
| 4305 | 4368 | break; |
| 4369 | + case IORING_OP_EPOLL_CTL: | |
| 4370 | + if (sqe) { | |
| 4371 | + ret = io_epoll_ctl_prep(req, sqe); | |
| 4372 | + if (ret) | |
| 4373 | + break; | |
| 4374 | + } | |
| 4375 | + ret = io_epoll_ctl(req, nxt, force_nonblock); | |
| 4376 | + break; | |
| 4306 | 4377 | default: |
| 4307 | 4378 | ret = -EINVAL; |
| 4308 | 4379 | break; |
| @@ -112,6 +112,7 @@ enum { · 111 unmodified lines | ||
| 112 | 112 | IORING_OP_SEND, |
| 113 | 113 | IORING_OP_RECV, |
| 114 | 114 | IORING_OP_OPENAT2, |
| 115 | + IORING_OP_EPOLL_CTL, | |
| 115 | 116 | |
| 116 | 117 | /* this goes last, obviously */ |
| 117 | 118 | IORING_OP_LAST, |