Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'io_uring-6.16-20250606' of git://git.kernel.dk/linux

Pull io_uring fixes from Jens Axboe:

- Fix for a regression introduced in this merge window, where the 'id'
passed to xa_find() for ifq lookup is uninitialized

- Fix for zcrx release on registration failure. From 6.15, going to
stable

- Tweak for recv bundles, where msg_inq should be > 1 before being used
to gate a retry event

- Pavel doesnt want to be a maintainer anymore, remove him from the
MAINTAINERS entry

- Limit legacy kbuf registrations to 64k, which is the size of the
buffer ID field anyway. Hence it's nonsensical to support more than
that, and the only purpose that serves is to have syzbot trigger long
exit delays for heavily configured debug kernels

- Fix for the io_uring futex handling, which got broken for
FUTEX2_PRIVATE by a generic futex commit adding private hashes

* tag 'io_uring-6.16-20250606' of git://git.kernel.dk/linux:
io_uring/futex: mark wait requests as inflight
io_uring/futex: get rid of struct io_futex addr union
io_uring/kbuf: limit legacy provided buffer lists to USHRT_MAX
MAINTAINERS: remove myself from io_uring
io_uring/net: only consider msg_inq if larger than 1
io_uring/zcrx: fix area release on registration failure
io_uring/zcrx: init id for xa_find

+37 -13
-1
MAINTAINERS
··· 12670 12670 12671 12671 IO_URING 12672 12672 M: Jens Axboe <axboe@kernel.dk> 12673 - M: Pavel Begunkov <asml.silence@gmail.com> 12674 12673 L: io-uring@vger.kernel.org 12675 12674 S: Maintained 12676 12675 T: git git://git.kernel.dk/linux-block
+6 -5
io_uring/futex.c
··· 14 14 15 15 struct io_futex { 16 16 struct file *file; 17 - union { 18 - u32 __user *uaddr; 19 - struct futex_waitv __user *uwaitv; 20 - }; 17 + void __user *uaddr; 21 18 unsigned long futex_val; 22 19 unsigned long futex_mask; 23 20 unsigned long futexv_owned; ··· 145 148 !futex_validate_input(iof->futex_flags, iof->futex_mask)) 146 149 return -EINVAL; 147 150 151 + /* Mark as inflight, so file exit cancelation will find it */ 152 + io_req_track_inflight(req); 148 153 return 0; 149 154 } 150 155 ··· 185 186 if (!futexv) 186 187 return -ENOMEM; 187 188 188 - ret = futex_parse_waitv(futexv, iof->uwaitv, iof->futex_nr, 189 + ret = futex_parse_waitv(futexv, iof->uaddr, iof->futex_nr, 189 190 io_futex_wakev_fn, req); 190 191 if (ret) { 191 192 kfree(futexv); 192 193 return ret; 193 194 } 194 195 196 + /* Mark as inflight, so file exit cancelation will find it */ 197 + io_req_track_inflight(req); 195 198 iof->futexv_owned = 0; 196 199 iof->futexv_unqueued = 0; 197 200 req->flags |= REQ_F_ASYNC_DATA;
+6 -1
io_uring/io_uring.c
··· 408 408 req->flags &= ~IO_REQ_CLEAN_FLAGS; 409 409 } 410 410 411 - static inline void io_req_track_inflight(struct io_kiocb *req) 411 + /* 412 + * Mark the request as inflight, so that file cancelation will find it. 413 + * Can be used if the file is an io_uring instance, or if the request itself 414 + * relies on ->mm being alive for the duration of the request. 415 + */ 416 + inline void io_req_track_inflight(struct io_kiocb *req) 412 417 { 413 418 if (!(req->flags & REQ_F_INFLIGHT)) { 414 419 req->flags |= REQ_F_INFLIGHT;
+1
io_uring/io_uring.h
··· 83 83 bool io_req_post_cqe(struct io_kiocb *req, s32 res, u32 cflags); 84 84 void __io_commit_cqring_flush(struct io_ring_ctx *ctx); 85 85 86 + void io_req_track_inflight(struct io_kiocb *req); 86 87 struct file *io_file_get_normal(struct io_kiocb *req, int fd); 87 88 struct file *io_file_get_fixed(struct io_kiocb *req, int fd, 88 89 unsigned issue_flags);
+15 -2
io_uring/kbuf.c
··· 108 108 buf = req->kbuf; 109 109 bl = io_buffer_get_list(ctx, buf->bgid); 110 110 list_add(&buf->list, &bl->buf_list); 111 + bl->nbufs++; 111 112 req->flags &= ~REQ_F_BUFFER_SELECTED; 112 113 113 114 io_ring_submit_unlock(ctx, issue_flags); ··· 123 122 124 123 kbuf = list_first_entry(&bl->buf_list, struct io_buffer, list); 125 124 list_del(&kbuf->list); 125 + bl->nbufs--; 126 126 if (*len == 0 || *len > kbuf->len) 127 127 *len = kbuf->len; 128 128 if (list_empty(&bl->buf_list)) ··· 392 390 for (i = 0; i < nbufs && !list_empty(&bl->buf_list); i++) { 393 391 nxt = list_first_entry(&bl->buf_list, struct io_buffer, list); 394 392 list_del(&nxt->list); 393 + bl->nbufs--; 395 394 kfree(nxt); 396 395 cond_resched(); 397 396 } ··· 494 491 { 495 492 struct io_buffer *buf; 496 493 u64 addr = pbuf->addr; 497 - int i, bid = pbuf->bid; 494 + int ret = -ENOMEM, i, bid = pbuf->bid; 498 495 499 496 for (i = 0; i < pbuf->nbufs; i++) { 497 + /* 498 + * Nonsensical to have more than sizeof(bid) buffers in a 499 + * buffer list, as the application then has no way of knowing 500 + * which duplicate bid refers to what buffer. 501 + */ 502 + if (bl->nbufs == USHRT_MAX) { 503 + ret = -EOVERFLOW; 504 + break; 505 + } 500 506 buf = kmalloc(sizeof(*buf), GFP_KERNEL_ACCOUNT); 501 507 if (!buf) 502 508 break; 503 509 504 510 list_add_tail(&buf->list, &bl->buf_list); 511 + bl->nbufs++; 505 512 buf->addr = addr; 506 513 buf->len = min_t(__u32, pbuf->len, MAX_RW_COUNT); 507 514 buf->bid = bid; ··· 521 508 cond_resched(); 522 509 } 523 510 524 - return i ? 0 : -ENOMEM; 511 + return i ? 0 : ret; 525 512 } 526 513 527 514 static int __io_manage_buffers_legacy(struct io_kiocb *req,
+3
io_uring/kbuf.h
··· 21 21 struct list_head buf_list; 22 22 struct io_uring_buf_ring *buf_ring; 23 23 }; 24 + /* count of classic/legacy buffers in buffer list */ 25 + int nbufs; 26 + 24 27 __u16 bgid; 25 28 26 29 /* below is for ring provided buffers */
+2 -2
io_uring/net.c
··· 832 832 * If more is available AND it was a full transfer, retry and 833 833 * append to this one 834 834 */ 835 - if (!sr->retry && kmsg->msg.msg_inq > 0 && this_ret > 0 && 835 + if (!sr->retry && kmsg->msg.msg_inq > 1 && this_ret > 0 && 836 836 !iov_iter_count(&kmsg->msg.msg_iter)) { 837 837 req->cqe.flags = cflags & ~CQE_F_MASK; 838 838 sr->len = kmsg->msg.msg_inq; ··· 1070 1070 arg.mode |= KBUF_MODE_FREE; 1071 1071 } 1072 1072 1073 - if (kmsg->msg.msg_inq > 0) 1073 + if (kmsg->msg.msg_inq > 1) 1074 1074 arg.max_len = min_not_zero(sr->len, kmsg->msg.msg_inq); 1075 1075 1076 1076 ret = io_buffers_peek(req, &arg);
+4 -2
io_uring/zcrx.c
··· 366 366 367 367 static void io_zcrx_free_area(struct io_zcrx_area *area) 368 368 { 369 - io_zcrx_unmap_area(area->ifq, area); 369 + if (area->ifq) 370 + io_zcrx_unmap_area(area->ifq, area); 370 371 io_release_area_mem(&area->mem); 371 372 372 373 kvfree(area->freelist); ··· 632 631 void io_unregister_zcrx_ifqs(struct io_ring_ctx *ctx) 633 632 { 634 633 struct io_zcrx_ifq *ifq; 635 - unsigned long id; 636 634 637 635 lockdep_assert_held(&ctx->uring_lock); 638 636 639 637 while (1) { 640 638 scoped_guard(mutex, &ctx->mmap_lock) { 639 + unsigned long id = 0; 640 + 641 641 ifq = xa_find(&ctx->zcrx_ctxs, &id, ULONG_MAX, XA_PRESENT); 642 642 if (ifq) 643 643 xa_erase(&ctx->zcrx_ctxs, id);