io_uring/net: wire up IORING_CQE_F_SOCK_NONEMPTY for accept net-accept-more net-accept-more-20240515
authorJens Axboe <axboe@kernel.dk>
Thu, 9 May 2024 15:41:10 +0000 (09:41 -0600)
committerJens Axboe <axboe@kernel.dk>
Tue, 14 May 2024 00:19:23 +0000 (18:19 -0600)
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@apple.com>
Acked-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
io_uring/net.c

index d4d1fc93635cbf0c323fb5dd350f6470878e42dc..0a48596429d9f53edd252a58435619654f7ee7a0 100644 (file)
@@ -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 @@ retry:
                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 @@ retry:
                                                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;
 }