Skip to content

Commit 9d88bb9

Browse files
committed
Merge tag 'io_uring-7.1-20260430' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux
Pull io_uring fixes from Jens Axboe: - Remove dead struct io_buffer_list member - Fix for incrementally consumed buffers with recvmsg multishot, which requires a minimum value left in a buffer for any receive for the headers. If there's still a bit of buffer left but it's smaller than that value, then userspace will see a spurious -EFAULT returned in the CQE - Locking fix for the DEFER_TASKRUN retry list, which otherwise could race with fallback cancelations. If the task is exiting with task_work left in both the normal and retry list AND the exit cleanup races with the task running task work, then entries could either be doubly completed or lost - Cap NAPI busy poll timeout to something sane, to avoid syzbot running into excessive polling and triggering warnings around that * tag 'io_uring-7.1-20260430' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux: io_uring/tw: serialize ctx->retry_llist with ->uring_lock io_uring/napi: cap busy_poll_to 10 msec io_uring/kbuf: support min length left for incremental buffers io_uring/kbuf: kill dead struct io_buffer_list 'nr_entries' member
2 parents 33d0c9c + 17666e2 commit 9d88bb9

5 files changed

Lines changed: 29 additions & 5 deletions

File tree

include/uapi/linux/io_uring.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -905,7 +905,8 @@ struct io_uring_buf_reg {
905905
__u32 ring_entries;
906906
__u16 bgid;
907907
__u16 flags;
908-
__u64 resv[3];
908+
__u32 min_left;
909+
__u32 resv[5];
909910
};
910911

911912
/* argument for IORING_REGISTER_PBUF_STATUS */

io_uring/kbuf.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ static bool io_kbuf_inc_commit(struct io_buffer_list *bl, int len)
4747
this_len = min_t(u32, len, buf_len);
4848
buf_len -= this_len;
4949
/* Stop looping for invalid buffer length of 0 */
50-
if (buf_len || !this_len) {
50+
if (buf_len > bl->min_left_sub_one || !this_len) {
5151
WRITE_ONCE(buf->addr, READ_ONCE(buf->addr) + this_len);
5252
WRITE_ONCE(buf->len, buf_len);
5353
return false;
@@ -637,6 +637,10 @@ int io_register_pbuf_ring(struct io_ring_ctx *ctx, void __user *arg)
637637
if (reg.ring_entries >= 65536)
638638
return -EINVAL;
639639

640+
/* minimum left byte count is a property of incremental buffers */
641+
if (!(reg.flags & IOU_PBUF_RING_INC) && reg.min_left)
642+
return -EINVAL;
643+
640644
bl = io_buffer_get_list(ctx, reg.bgid);
641645
if (bl) {
642646
/* if mapped buffer ring OR classic exists, don't allow */
@@ -680,10 +684,11 @@ int io_register_pbuf_ring(struct io_ring_ctx *ctx, void __user *arg)
680684
}
681685
#endif
682686

683-
bl->nr_entries = reg.ring_entries;
684687
bl->mask = reg.ring_entries - 1;
685688
bl->flags |= IOBL_BUF_RING;
686689
bl->buf_ring = br;
690+
if (reg.min_left)
691+
bl->min_left_sub_one = reg.min_left - 1;
687692
if (reg.flags & IOU_PBUF_RING_INC)
688693
bl->flags |= IOBL_INC;
689694
ret = io_buffer_add_list(ctx, bl, reg.bgid);

io_uring/kbuf.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,18 @@ struct io_buffer_list {
2727
__u16 bgid;
2828

2929
/* below is for ring provided buffers */
30-
__u16 nr_entries;
3130
__u16 head;
3231
__u16 mask;
3332

3433
__u16 flags;
3534

35+
/*
36+
* minimum required amount to be left to reuse an incrementally
37+
* consumed buffer. If less than this is left at consumption time,
38+
* buffer is done and head is incremented to the next buffer.
39+
*/
40+
__u32 min_left_sub_one;
41+
3642
struct io_mapped_region region;
3743
};
3844

io_uring/napi.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,8 @@ static int io_napi_register_napi(struct io_ring_ctx *ctx,
276276
/* clean the napi list for new settings */
277277
io_napi_free(ctx);
278278
WRITE_ONCE(ctx->napi_track_mode, napi->op_param);
279+
/* cap NAPI at 10 msec of spin time */
280+
napi->busy_poll_to = min(10000, napi->busy_poll_to);
279281
WRITE_ONCE(ctx->napi_busy_poll_dt, napi->busy_poll_to * NSEC_PER_USEC);
280282
WRITE_ONCE(ctx->napi_prefer_busy_poll, !!napi->prefer_busy_poll);
281283
return 0;

io_uring/tw.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,8 +273,18 @@ void io_req_task_work_add_remote(struct io_kiocb *req, unsigned flags)
273273

274274
void __cold io_move_task_work_from_local(struct io_ring_ctx *ctx)
275275
{
276-
struct llist_node *node = llist_del_all(&ctx->work_llist);
276+
struct llist_node *node;
277277

278+
/*
279+
* Running the work items may utilize ->retry_llist as a means
280+
* for capping the number of task_work entries run at the same
281+
* time. But that list can potentially race with moving the work
282+
* from here, if the task is exiting. As any normal task_work
283+
* running holds ->uring_lock already, just guard this slow path
284+
* with ->uring_lock to avoid racing on ->retry_llist.
285+
*/
286+
guard(mutex)(&ctx->uring_lock);
287+
node = llist_del_all(&ctx->work_llist);
278288
__io_fallback_tw(node, false);
279289
node = llist_del_all(&ctx->retry_llist);
280290
__io_fallback_tw(node, false);

0 commit comments

Comments
 (0)