Skip to content

Commit 6a8afb9

Browse files
committed
io_uring/net: allow multishot receive per-invocation cap
If an application is handling multiple receive streams using recv multishot, then the amount of retries and buffer peeking for multishot and bundles can process too much per socket before moving on. This isn't directly controllable by the application. By default, io_uring will retry a recv MULTISHOT_MAX_RETRY (32) times, if the socket keeps having data to receive. And if using bundles, then each bundle peek will potentially map up to PEEK_MAX_IMPORT (256) iovecs of data. Once these limits are hit, then a requeue operation will be done, where the request will get retried after other pending requests have had a time to get executed. Add support for capping the per-invocation receive length, before a requeue condition is considered for each receive. This is done by setting sqe->mshot_len to the byte value. For example, if this is set to 1024, then each receive will be requeued by 1024 bytes received. Link: https://lore.kernel.org/io-uring/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 3919b69 commit 6a8afb9

1 file changed

Lines changed: 17 additions & 6 deletions

File tree

io_uring/net.c

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ struct io_sr_msg {
7575
u16 flags;
7676
/* initialised and used only by !msg send variants */
7777
u16 buf_group;
78+
unsigned mshot_len;
7879
void __user *msg_control;
7980
/* used only for send zerocopy */
8081
struct io_kiocb *notif;
@@ -87,9 +88,11 @@ struct io_sr_msg {
8788
enum sr_retry_flags {
8889
IORING_RECV_RETRY = (1U << 15),
8990
IORING_RECV_PARTIAL_MAP = (1U << 14),
91+
IORING_RECV_MSHOT_CAP = (1U << 13),
9092

9193
IORING_RECV_RETRY_CLEAR = IORING_RECV_RETRY | IORING_RECV_PARTIAL_MAP,
92-
IORING_RECV_NO_RETRY = IORING_RECV_RETRY | IORING_RECV_PARTIAL_MAP,
94+
IORING_RECV_NO_RETRY = IORING_RECV_RETRY | IORING_RECV_PARTIAL_MAP |
95+
IORING_RECV_MSHOT_CAP,
9396
};
9497

9598
/*
@@ -199,7 +202,7 @@ static inline void io_mshot_prep_retry(struct io_kiocb *req,
199202
req->flags &= ~REQ_F_BL_EMPTY;
200203
sr->done_io = 0;
201204
sr->flags &= ~IORING_RECV_RETRY_CLEAR;
202-
sr->len = 0; /* get from the provided buffer */
205+
sr->len = sr->mshot_len;
203206
}
204207

205208
static int io_net_import_vec(struct io_kiocb *req, struct io_async_msghdr *iomsg,
@@ -787,13 +790,14 @@ int io_recvmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
787790
sr->buf_group = req->buf_index;
788791
req->buf_list = NULL;
789792
}
793+
sr->mshot_len = 0;
790794
if (sr->flags & IORING_RECV_MULTISHOT) {
791795
if (!(req->flags & REQ_F_BUFFER_SELECT))
792796
return -EINVAL;
793797
if (sr->msg_flags & MSG_WAITALL)
794798
return -EINVAL;
795-
if (req->opcode == IORING_OP_RECV && sr->len)
796-
return -EINVAL;
799+
if (req->opcode == IORING_OP_RECV)
800+
sr->mshot_len = sr->len;
797801
req->flags |= REQ_F_APOLL_MULTISHOT;
798802
}
799803
if (sr->flags & IORING_RECVSEND_BUNDLE) {
@@ -834,6 +838,8 @@ static inline bool io_recv_finish(struct io_kiocb *req, int *ret,
834838
issue_flags);
835839
if (sr->flags & IORING_RECV_RETRY)
836840
cflags = req->cqe.flags | (cflags & CQE_F_MASK);
841+
if (sr->mshot_len && *ret >= sr->mshot_len)
842+
sr->flags |= IORING_RECV_MSHOT_CAP;
837843
/* bundle with no more immediate buffers, we're done */
838844
if (req->flags & REQ_F_BL_EMPTY)
839845
goto finish;
@@ -864,10 +870,13 @@ static inline bool io_recv_finish(struct io_kiocb *req, int *ret,
864870
io_mshot_prep_retry(req, kmsg);
865871
/* Known not-empty or unknown state, retry */
866872
if (cflags & IORING_CQE_F_SOCK_NONEMPTY || kmsg->msg.msg_inq < 0) {
867-
if (sr->nr_multishot_loops++ < MULTISHOT_MAX_RETRY)
873+
if (sr->nr_multishot_loops++ < MULTISHOT_MAX_RETRY &&
874+
!(sr->flags & IORING_RECV_MSHOT_CAP)) {
868875
return false;
876+
}
869877
/* mshot retries exceeded, force a requeue */
870878
sr->nr_multishot_loops = 0;
879+
sr->flags &= ~IORING_RECV_MSHOT_CAP;
871880
if (issue_flags & IO_URING_F_MULTISHOT)
872881
*ret = IOU_REQUEUE;
873882
}
@@ -1080,7 +1089,9 @@ static int io_recv_buf_select(struct io_kiocb *req, struct io_async_msghdr *kmsg
10801089
arg.mode |= KBUF_MODE_FREE;
10811090
}
10821091

1083-
if (kmsg->msg.msg_inq > 1)
1092+
if (*len)
1093+
arg.max_len = *len;
1094+
else if (kmsg->msg.msg_inq > 1)
10841095
arg.max_len = min_not_zero(*len, kmsg->msg.msg_inq);
10851096

10861097
ret = io_buffers_peek(req, &arg);

0 commit comments

Comments
 (0)