This allows an application to call accept4() in an async fashion. Like other opcodes, we first try a non-blocking accept, then punt to async context if we have to.
Unified · Split
| @@ -1686,6 +1686,40 @@ static int io_recvmsg(struct io_kiocb *req, const struct io_uring_sqe *sqe, · 1685 unmodified lines | ||
| 1686 | 1686 | #endif |
| 1687 | 1687 | } |
| 1688 | 1688 | |
| 1689 | +static int io_accept(struct io_kiocb *req, const struct io_uring_sqe *sqe, | |
| 1690 | + struct io_kiocb **nxt, bool force_nonblock) | |
| 1691 | +{ | |
| 1692 | +#if defined(CONFIG_NET) | |
| 1693 | + struct sockaddr __user *addr; | |
| 1694 | + int __user *addr_len; | |
| 1695 | + unsigned file_flags; | |
| 1696 | + int flags, ret; | |
| 1697 | + | |
| 1698 | + if (unlikely(req->ctx->flags & (IORING_SETUP_IOPOLL|IORING_SETUP_SQPOLL))) | |
| 1699 | + return -EINVAL; | |
| 1700 | + if (sqe->ioprio || sqe->off || sqe->len || sqe->buf_index) | |
| 1701 | + return -EINVAL; | |
| 1702 | + | |
| 1703 | + addr = (struct sockaddr __user *) (unsigned long) READ_ONCE(sqe->addr); | |
| 1704 | + addr_len = (int __user *) (unsigned long) READ_ONCE(sqe->addr2); | |
| 1705 | + flags = READ_ONCE(sqe->accept_flags); | |
| 1706 | + file_flags = force_nonblock ? O_NONBLOCK : 0; | |
| 1707 | + | |
| 1708 | + ret = __sys_accept4_file(req->file, file_flags, addr, addr_len, flags); | |
| 1709 | + if (ret == -EAGAIN && force_nonblock) { | |
| 1710 | + req->work.flags |= IO_WQ_WORK_NEEDS_FILES; | |
| 1711 | + return -EAGAIN; | |
| 1712 | + } | |
| 1713 | + if (ret < 0 && (req->flags & REQ_F_LINK)) | |
| 1714 | + req->flags |= REQ_F_FAIL_LINK; | |
| 1715 | + io_cqring_add_event(req->ctx, sqe->user_data, ret); | |
| 1716 | + io_put_req(req, nxt); | |
| 1717 | + return 0; | |
| 1718 | +#else | |
| 1719 | + return -EOPNOTSUPP; | |
| 1720 | +#endif | |
| 1721 | +} | |
| 1722 | + | |
| 1689 | 1723 | static void io_poll_remove_one(struct io_kiocb *req) |
| 1690 | 1724 | { |
| 1691 | 1725 | struct io_poll_iocb *poll = &req->poll; |
| @@ -2173,6 +2207,9 @@ static int __io_submit_sqe(struct io_ring_ctx *ctx, struct io_kiocb *req, · 481 unmodified lines | ||
| 2173 | 2207 | case IORING_OP_TIMEOUT_REMOVE: |
| 2174 | 2208 | ret = io_timeout_remove(req, s->sqe); |
| 2175 | 2209 | break; |
| 2210 | + case IORING_OP_ACCEPT: | |
| 2211 | + ret = io_accept(req, s->sqe, nxt, force_nonblock); | |
| 2212 | + break; | |
| 2176 | 2213 | default: |
| 2177 | 2214 | ret = -EINVAL; |
| 2178 | 2215 | break; |
| @@ -19,7 +19,10 @@ struct io_uring_sqe { · 18 unmodified lines | ||
| 19 | 19 | __u8 flags; /* IOSQE_ flags */ |
| 20 | 20 | __u16 ioprio; /* ioprio for the request */ |
| 21 | 21 | __s32 fd; /* file descriptor to do IO on */ |
| 22 | − __u64 off; /* offset into file */ | |
| 22 | + union { | |
| 23 | + __u64 off; /* offset into file */ | |
| 24 | + __u64 addr2; | |
| 25 | + }; | |
| 23 | 26 | __u64 addr; /* pointer to buffer or iovecs */ |
| 24 | 27 | __u32 len; /* buffer size or number of iovecs */ |
| 25 | 28 | union { |
| @@ -29,6 +32,7 @@ struct io_uring_sqe { · 3 unmodified lines | ||
| 29 | 32 | __u32 sync_range_flags; |
| 30 | 33 | __u32 msg_flags; |
| 31 | 34 | __u32 timeout_flags; |
| 35 | + __u32 accept_flags; | |
| 32 | 36 | }; |
| 33 | 37 | __u64 user_data; /* data to be passed back at completion time */ |
| 34 | 38 | union { |
| @@ -65,6 +69,7 @@ struct io_uring_sqe { · 30 unmodified lines | ||
| 65 | 69 | #define IORING_OP_RECVMSG 10 |
| 66 | 70 | #define IORING_OP_TIMEOUT 11 |
| 67 | 71 | #define IORING_OP_TIMEOUT_REMOVE 12 |
| 72 | +#define IORING_OP_ACCEPT 13 | |
| 68 | 73 | |
| 69 | 74 | /* |
| 70 | 75 | * sqe->fsync_flags |