Skip to content

Commit 6699ec9

Browse files
spikehaxboe
authored andcommitted
io_uring/zcrx: add a read limit to recvzc requests
Currently multishot recvzc requests have no read limit and will remain active so as long as the socket remains open. But, there are sometimes a need to do a fixed length read e.g. peeking at some data in the socket. Add a length limit to recvzc requests `len`. A value of 0 means no limit which is the previous behaviour. A positive value N specifies how many bytes to read from the socket. Data will still be posted in aux completions, as before. This could be split across multiple frags. But the primary recvzc request will now complete once N bytes have been read. The completion of the recvzc request will have res and cflags both set to 0. Signed-off-by: David Wei <[email protected]> Reviewed-by: Pavel Begunkov <[email protected]> Link: https://lore.kernel.org/r/[email protected] [axboe: fixup io_zcrx_recv() for !CONFIG_NET] Signed-off-by: Jens Axboe <[email protected]>
1 parent 92ade52 commit 6699ec9

File tree

3 files changed

+24
-9
lines changed

3 files changed

+24
-9
lines changed

io_uring/net.c

+13-3
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ struct io_recvzc {
9494
struct file *file;
9595
unsigned msg_flags;
9696
u16 flags;
97+
u32 len;
9798
struct io_zcrx_ifq *ifq;
9899
};
99100

@@ -1241,7 +1242,7 @@ int io_recvzc_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
12411242
unsigned ifq_idx;
12421243

12431244
if (unlikely(sqe->file_index || sqe->addr2 || sqe->addr ||
1244-
sqe->len || sqe->addr3))
1245+
sqe->addr3))
12451246
return -EINVAL;
12461247

12471248
ifq_idx = READ_ONCE(sqe->zcrx_ifq_idx);
@@ -1250,7 +1251,7 @@ int io_recvzc_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
12501251
zc->ifq = req->ctx->ifq;
12511252
if (!zc->ifq)
12521253
return -EINVAL;
1253-
1254+
zc->len = READ_ONCE(sqe->len);
12541255
zc->flags = READ_ONCE(sqe->ioprio);
12551256
zc->msg_flags = READ_ONCE(sqe->msg_flags);
12561257
if (zc->msg_flags)
@@ -1270,6 +1271,7 @@ int io_recvzc(struct io_kiocb *req, unsigned int issue_flags)
12701271
{
12711272
struct io_recvzc *zc = io_kiocb_to_cmd(req, struct io_recvzc);
12721273
struct socket *sock;
1274+
unsigned int len;
12731275
int ret;
12741276

12751277
if (!(req->flags & REQ_F_POLLED) &&
@@ -1280,8 +1282,16 @@ int io_recvzc(struct io_kiocb *req, unsigned int issue_flags)
12801282
if (unlikely(!sock))
12811283
return -ENOTSOCK;
12821284

1285+
len = zc->len;
12831286
ret = io_zcrx_recv(req, zc->ifq, sock, zc->msg_flags | MSG_DONTWAIT,
1284-
issue_flags);
1287+
issue_flags, &zc->len);
1288+
if (len && zc->len == 0) {
1289+
io_req_set_res(req, 0, 0);
1290+
1291+
if (issue_flags & IO_URING_F_MULTISHOT)
1292+
return IOU_STOP_MULTISHOT;
1293+
return IOU_OK;
1294+
}
12851295
if (unlikely(ret <= 0) && ret != -EAGAIN) {
12861296
if (ret == -ERESTARTSYS)
12871297
ret = -EINTR;

io_uring/zcrx.c

+9-4
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,7 @@ io_zcrx_recv_skb(read_descriptor_t *desc, struct sk_buff *skb,
817817
int i, copy, end, off;
818818
int ret = 0;
819819

820+
len = min_t(size_t, len, desc->count);
820821
if (unlikely(args->nr_skbs++ > IO_SKBS_PER_CALL_LIMIT))
821822
return -EAGAIN;
822823

@@ -894,26 +895,30 @@ io_zcrx_recv_skb(read_descriptor_t *desc, struct sk_buff *skb,
894895
out:
895896
if (offset == start_off)
896897
return ret;
898+
desc->count -= (offset - start_off);
897899
return offset - start_off;
898900
}
899901

900902
static int io_zcrx_tcp_recvmsg(struct io_kiocb *req, struct io_zcrx_ifq *ifq,
901903
struct sock *sk, int flags,
902-
unsigned issue_flags)
904+
unsigned issue_flags, unsigned int *outlen)
903905
{
906+
unsigned int len = *outlen;
904907
struct io_zcrx_args args = {
905908
.req = req,
906909
.ifq = ifq,
907910
.sock = sk->sk_socket,
908911
};
909912
read_descriptor_t rd_desc = {
910-
.count = 1,
913+
.count = len ? len : UINT_MAX,
911914
.arg.data = &args,
912915
};
913916
int ret;
914917

915918
lock_sock(sk);
916919
ret = tcp_read_sock(sk, &rd_desc, io_zcrx_recv_skb);
920+
if (len && ret > 0)
921+
*outlen = len - ret;
917922
if (ret <= 0) {
918923
if (ret < 0 || sock_flag(sk, SOCK_DONE))
919924
goto out;
@@ -942,7 +947,7 @@ static int io_zcrx_tcp_recvmsg(struct io_kiocb *req, struct io_zcrx_ifq *ifq,
942947

943948
int io_zcrx_recv(struct io_kiocb *req, struct io_zcrx_ifq *ifq,
944949
struct socket *sock, unsigned int flags,
945-
unsigned issue_flags)
950+
unsigned issue_flags, unsigned int *len)
946951
{
947952
struct sock *sk = sock->sk;
948953
const struct proto *prot = READ_ONCE(sk->sk_prot);
@@ -951,5 +956,5 @@ int io_zcrx_recv(struct io_kiocb *req, struct io_zcrx_ifq *ifq,
951956
return -EPROTONOSUPPORT;
952957

953958
sock_rps_record_flow(sk);
954-
return io_zcrx_tcp_recvmsg(req, ifq, sk, flags, issue_flags);
959+
return io_zcrx_tcp_recvmsg(req, ifq, sk, flags, issue_flags, len);
955960
}

io_uring/zcrx.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ void io_unregister_zcrx_ifqs(struct io_ring_ctx *ctx);
4646
void io_shutdown_zcrx_ifqs(struct io_ring_ctx *ctx);
4747
int io_zcrx_recv(struct io_kiocb *req, struct io_zcrx_ifq *ifq,
4848
struct socket *sock, unsigned int flags,
49-
unsigned issue_flags);
49+
unsigned issue_flags, unsigned int *len);
5050
#else
5151
static inline int io_register_zcrx_ifq(struct io_ring_ctx *ctx,
5252
struct io_uring_zcrx_ifq_reg __user *arg)
@@ -61,7 +61,7 @@ static inline void io_shutdown_zcrx_ifqs(struct io_ring_ctx *ctx)
6161
}
6262
static inline int io_zcrx_recv(struct io_kiocb *req, struct io_zcrx_ifq *ifq,
6363
struct socket *sock, unsigned int flags,
64-
unsigned issue_flags)
64+
unsigned issue_flags, unsigned int *len)
6565
{
6666
return -EOPNOTSUPP;
6767
}

0 commit comments

Comments
 (0)