Skip to content

Commit c7d15ba

Browse files
axboegregkh
authored andcommitted
io_uring/kbuf: flag partial buffer mappings
Commit 178b8ff upstream. A previous commit aborted mapping more for a non-incremental ring for bundle peeking, but depending on where in the process this peeking happened, it would not necessarily prevent a retry by the user. That can create gaps in the received/read data. Add struct buf_sel_arg->partial_map, which can pass this information back. The networking side can then map that to internal state and use it to gate retry as well. Since this necessitates a new flag, change io_sr_msg->retry to a retry_flags member, and store both the retry and partial map condition in there. Cc: stable@vger.kernel.org Fixes: 26ec15e ("io_uring/kbuf: don't truncate end buffer for multiple buffer peeks") Signed-off-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent c124f40 commit c7d15ba

3 files changed

Lines changed: 17 additions & 8 deletions

File tree

io_uring/kbuf.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ static int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg,
271271
if (len > arg->max_len) {
272272
len = arg->max_len;
273273
if (!(bl->flags & IOBL_INC)) {
274+
arg->partial_map = 1;
274275
if (iov != arg->iovs)
275276
break;
276277
buf->len = len;

io_uring/kbuf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ struct buf_sel_arg {
5555
size_t max_len;
5656
unsigned short nr_iovs;
5757
unsigned short mode;
58+
unsigned short partial_map;
5859
};
5960

6061
void __user *io_buffer_select(struct io_kiocb *req, size_t *len,

io_uring/net.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,17 @@ struct io_sr_msg {
7676
u16 flags;
7777
/* initialised and used only by !msg send variants */
7878
u16 buf_group;
79-
bool retry;
79+
unsigned short retry_flags;
8080
void __user *msg_control;
8181
/* used only for send zerocopy */
8282
struct io_kiocb *notif;
8383
};
8484

85+
enum sr_retry_flags {
86+
IO_SR_MSG_RETRY = 1,
87+
IO_SR_MSG_PARTIAL_MAP = 2,
88+
};
89+
8590
/*
8691
* Number of times we'll try and do receives if there's more data. If we
8792
* exceed this limit, then add us to the back of the queue and retry from
@@ -188,7 +193,7 @@ static inline void io_mshot_prep_retry(struct io_kiocb *req,
188193

189194
req->flags &= ~REQ_F_BL_EMPTY;
190195
sr->done_io = 0;
191-
sr->retry = false;
196+
sr->retry_flags = 0;
192197
sr->len = 0; /* get from the provided buffer */
193198
req->buf_index = sr->buf_group;
194199
}
@@ -401,7 +406,7 @@ int io_sendmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
401406
struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg);
402407

403408
sr->done_io = 0;
404-
sr->retry = false;
409+
sr->retry_flags = 0;
405410
sr->len = READ_ONCE(sqe->len);
406411
sr->flags = READ_ONCE(sqe->ioprio);
407412
if (sr->flags & ~SENDMSG_FLAGS)
@@ -759,7 +764,7 @@ int io_recvmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
759764
struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg);
760765

761766
sr->done_io = 0;
762-
sr->retry = false;
767+
sr->retry_flags = 0;
763768

764769
if (unlikely(sqe->file_index || sqe->addr2))
765770
return -EINVAL;
@@ -831,7 +836,7 @@ static inline bool io_recv_finish(struct io_kiocb *req, int *ret,
831836

832837
cflags |= io_put_kbufs(req, this_ret, io_bundle_nbufs(kmsg, this_ret),
833838
issue_flags);
834-
if (sr->retry)
839+
if (sr->retry_flags & IO_SR_MSG_RETRY)
835840
cflags = req->cqe.flags | (cflags & CQE_F_MASK);
836841
/* bundle with no more immediate buffers, we're done */
837842
if (req->flags & REQ_F_BL_EMPTY)
@@ -840,12 +845,12 @@ static inline bool io_recv_finish(struct io_kiocb *req, int *ret,
840845
* If more is available AND it was a full transfer, retry and
841846
* append to this one
842847
*/
843-
if (!sr->retry && kmsg->msg.msg_inq > 1 && this_ret > 0 &&
848+
if (!sr->retry_flags && kmsg->msg.msg_inq > 1 && this_ret > 0 &&
844849
!iov_iter_count(&kmsg->msg.msg_iter)) {
845850
req->cqe.flags = cflags & ~CQE_F_MASK;
846851
sr->len = kmsg->msg.msg_inq;
847852
sr->done_io += this_ret;
848-
sr->retry = true;
853+
sr->retry_flags |= IO_SR_MSG_RETRY;
849854
return false;
850855
}
851856
} else {
@@ -1089,6 +1094,8 @@ static int io_recv_buf_select(struct io_kiocb *req, struct io_async_msghdr *kmsg
10891094
kmsg->vec.iovec = arg.iovs;
10901095
req->flags |= REQ_F_NEED_CLEANUP;
10911096
}
1097+
if (arg.partial_map)
1098+
sr->retry_flags |= IO_SR_MSG_PARTIAL_MAP;
10921099

10931100
/* special case 1 vec, can be a fast path */
10941101
if (ret == 1) {
@@ -1285,7 +1292,7 @@ int io_send_zc_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
12851292
int ret;
12861293

12871294
zc->done_io = 0;
1288-
zc->retry = false;
1295+
zc->retry_flags = 0;
12891296

12901297
if (unlikely(READ_ONCE(sqe->__pad2[0]) || READ_ONCE(sqe->addr3)))
12911298
return -EINVAL;

0 commit comments

Comments
 (0)