If the given protocol supports passing back whether or not we had more pending accept post this one, pass back this information to userspace. This is done by setting IORING_CQE_F_SOCK_NONEMPTY in the CQE flags, just like we do for recv/recvmsg if there's more data available post a receive operation. We can also use this information to be smarter about multishot retry, as we don't need to do a pointless retry if we know for a fact that there aren't any more connections to accept. Suggested-by: Norman Maurer <norman_maurer@xxxxxxxxx> Signed-off-by: Jens Axboe <axboe@xxxxxxxxx> --- io_uring/net.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/io_uring/net.c b/io_uring/net.c index d4d1fc93635c..0a48596429d9 100644 --- a/io_uring/net.c +++ b/io_uring/net.c @@ -1533,6 +1533,7 @@ int io_accept(struct io_kiocb *req, unsigned int issue_flags) .flags = force_nonblock ? O_NONBLOCK : 0, }; struct file *file; + unsigned cflags; int ret, fd; if (!(req->flags & REQ_F_POLLED) && @@ -1545,6 +1546,8 @@ int io_accept(struct io_kiocb *req, unsigned int issue_flags) if (unlikely(fd < 0)) return fd; } + arg.err = 0; + arg.is_empty = -1; file = do_accept(req->file, &arg, accept->addr, accept->addr_len, accept->flags); if (IS_ERR(file)) { @@ -1573,17 +1576,26 @@ int io_accept(struct io_kiocb *req, unsigned int issue_flags) accept->file_slot); } + cflags = 0; + if (!arg.is_empty) + cflags |= IORING_CQE_F_SOCK_NONEMPTY; + if (!(req->flags & REQ_F_APOLL_MULTISHOT)) { - io_req_set_res(req, ret, 0); + io_req_set_res(req, ret, cflags); return IOU_OK; } if (ret < 0) return ret; - if (io_req_post_cqe(req, ret, IORING_CQE_F_MORE)) - goto retry; + if (io_req_post_cqe(req, ret, cflags | IORING_CQE_F_MORE)) { + if (cflags & IORING_CQE_F_SOCK_NONEMPTY || arg.is_empty == -1) + goto retry; + if (issue_flags & IO_URING_F_MULTISHOT) + return IOU_ISSUE_SKIP_COMPLETE; + return -EAGAIN; + } - io_req_set_res(req, ret, 0); + io_req_set_res(req, ret, cflags); return IOU_STOP_MULTISHOT; } -- 2.43.0