Skip to content

Commit 7c71a0a

Browse files
committed
io_uring/net: improve recv bundles
Current recv bundles are only supported for multishot receives, and additionally they also always post at least 2 CQEs if more data is available than what a buffer will hold. This happens because the initial bundle recv will do a single buffer, and then do the rest of what is in the socket as a followup receive. As shown in a test program, if 1k buffers are available and 32k is available to receive in the socket, you'd get the following completions: bundle=1, mshot=0 cqe res 1024 cqe res 1024 [...] cqe res 1024 bundle=1, mshot=1 cqe res 1024 cqe res 31744 where bundle=1 && mshot=0 will post 32 1k completions, and bundle=1 && mshot=1 will post a 1k completion and then a 31k completion. To support bundle recv without multishot, it's possible to simply retry the recv immediately and post a single completion, rather than split it into two completions. With the below patch, the same test looks as follows: bundle=1, mshot=0 cqe res 32768 bundle=1, mshot=1 cqe res 32768 where mshot=0 works fine for bundles, and both of them post just a single 32k completion rather than split it into separate completions. Posting fewer completions is always a nice win, and not needing multishot for proper bundle efficiency is nice for cases that can't necessarily use multishot. Reported-by: Norman Maurer <[email protected]> Link: https://lore.kernel.org/r/[email protected] Fixes: 2f9c951 ("io_uring/net: support bundles for recv") Signed-off-by: Jens Axboe <[email protected]>
1 parent 932de5e commit 7c71a0a

File tree

1 file changed

+18
-0
lines changed

1 file changed

+18
-0
lines changed

io_uring/net.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ struct io_sr_msg {
7676
/* initialised and used only by !msg send variants */
7777
u16 buf_group;
7878
u16 buf_index;
79+
bool retry;
7980
void __user *msg_control;
8081
/* used only for send zerocopy */
8182
struct io_kiocb *notif;
@@ -187,6 +188,7 @@ static inline void io_mshot_prep_retry(struct io_kiocb *req,
187188

188189
req->flags &= ~REQ_F_BL_EMPTY;
189190
sr->done_io = 0;
191+
sr->retry = false;
190192
sr->len = 0; /* get from the provided buffer */
191193
req->buf_index = sr->buf_group;
192194
}
@@ -402,6 +404,7 @@ int io_sendmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
402404
struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg);
403405

404406
sr->done_io = 0;
407+
sr->retry = false;
405408

406409
if (req->opcode != IORING_OP_SEND) {
407410
if (sqe->addr2 || sqe->file_index)
@@ -785,6 +788,7 @@ int io_recvmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
785788
struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg);
786789

787790
sr->done_io = 0;
791+
sr->retry = false;
788792

789793
if (unlikely(sqe->file_index || sqe->addr2))
790794
return -EINVAL;
@@ -833,6 +837,9 @@ int io_recvmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
833837
return io_recvmsg_prep_setup(req);
834838
}
835839

840+
/* bits to clear in old and inherit in new cflags on bundle retry */
841+
#define CQE_F_MASK (IORING_CQE_F_SOCK_NONEMPTY|IORING_CQE_F_MORE)
842+
836843
/*
837844
* Finishes io_recv and io_recvmsg.
838845
*
@@ -852,9 +859,19 @@ static inline bool io_recv_finish(struct io_kiocb *req, int *ret,
852859
if (sr->flags & IORING_RECVSEND_BUNDLE) {
853860
cflags |= io_put_kbufs(req, *ret, io_bundle_nbufs(kmsg, *ret),
854861
issue_flags);
862+
if (sr->retry)
863+
cflags = req->cqe.flags | (cflags & CQE_F_MASK);
855864
/* bundle with no more immediate buffers, we're done */
856865
if (req->flags & REQ_F_BL_EMPTY)
857866
goto finish;
867+
/* if more is available, retry and append to this one */
868+
if (!sr->retry && kmsg->msg.msg_inq > 0 && *ret > 0) {
869+
req->cqe.flags = cflags & ~CQE_F_MASK;
870+
sr->len = kmsg->msg.msg_inq;
871+
sr->done_io += *ret;
872+
sr->retry = true;
873+
return false;
874+
}
858875
} else {
859876
cflags |= io_put_kbuf(req, *ret, issue_flags);
860877
}
@@ -1233,6 +1250,7 @@ int io_send_zc_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
12331250
struct io_kiocb *notif;
12341251

12351252
zc->done_io = 0;
1253+
zc->retry = false;
12361254
req->flags |= REQ_F_POLL_NO_LAZY;
12371255

12381256
if (unlikely(READ_ONCE(sqe->__pad2[0]) || READ_ONCE(sqe->addr3)))

0 commit comments

Comments
 (0)