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-7.0-20260320' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux

Pull io_uring fixes from Jens Axboe:

- A bit of a work-around for AF_UNIX recv multishot, as the in-kernel
implementation doesn't properly signal EOF. We'll likely rework this
one going forward, but the fix is sufficient for now

- Two fixes for incrementally consumed buffers, for non-pollable files
and for 0 byte reads

* tag 'io_uring-7.0-20260320' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux:
io_uring/kbuf: propagate BUF_MORE through early buffer commit path
io_uring/kbuf: fix missing BUF_MORE for incremental buffers at EOF
io_uring/poll: fix multishot recv missing EOF on wakeup race

+21 -5
+3
include/linux/io_uring_types.h
··· 541 541 REQ_F_BL_NO_RECYCLE_BIT, 542 542 REQ_F_BUFFERS_COMMIT_BIT, 543 543 REQ_F_BUF_NODE_BIT, 544 + REQ_F_BUF_MORE_BIT, 544 545 REQ_F_HAS_METADATA_BIT, 545 546 REQ_F_IMPORT_BUFFER_BIT, 546 547 REQ_F_SQE_COPIED_BIT, ··· 627 626 REQ_F_BUFFERS_COMMIT = IO_REQ_FLAG(REQ_F_BUFFERS_COMMIT_BIT), 628 627 /* buf node is valid */ 629 628 REQ_F_BUF_NODE = IO_REQ_FLAG(REQ_F_BUF_NODE_BIT), 629 + /* incremental buffer consumption, more space available */ 630 + REQ_F_BUF_MORE = IO_REQ_FLAG(REQ_F_BUF_MORE_BIT), 630 631 /* request has read/write metadata assigned */ 631 632 REQ_F_HAS_METADATA = IO_REQ_FLAG(REQ_F_HAS_METADATA_BIT), 632 633 /*
+11 -3
io_uring/kbuf.c
··· 34 34 35 35 static bool io_kbuf_inc_commit(struct io_buffer_list *bl, int len) 36 36 { 37 + /* No data consumed, return false early to avoid consuming the buffer */ 38 + if (!len) 39 + return false; 40 + 37 41 while (len) { 38 42 struct io_uring_buf *buf; 39 43 u32 buf_len, this_len; ··· 216 212 sel.addr = u64_to_user_ptr(READ_ONCE(buf->addr)); 217 213 218 214 if (io_should_commit(req, issue_flags)) { 219 - io_kbuf_commit(req, sel.buf_list, *len, 1); 215 + if (!io_kbuf_commit(req, sel.buf_list, *len, 1)) 216 + req->flags |= REQ_F_BUF_MORE; 220 217 sel.buf_list = NULL; 221 218 } 222 219 return sel; ··· 350 345 */ 351 346 if (ret > 0) { 352 347 req->flags |= REQ_F_BUFFERS_COMMIT | REQ_F_BL_NO_RECYCLE; 353 - io_kbuf_commit(req, sel->buf_list, arg->out_len, ret); 348 + if (!io_kbuf_commit(req, sel->buf_list, arg->out_len, ret)) 349 + req->flags |= REQ_F_BUF_MORE; 354 350 } 355 351 } else { 356 352 ret = io_provided_buffers_select(req, &arg->out_len, sel->buf_list, arg->iovs); ··· 397 391 398 392 if (bl) 399 393 ret = io_kbuf_commit(req, bl, len, nr); 394 + if (ret && (req->flags & REQ_F_BUF_MORE)) 395 + ret = false; 400 396 401 - req->flags &= ~REQ_F_BUFFER_RING; 397 + req->flags &= ~(REQ_F_BUFFER_RING | REQ_F_BUF_MORE); 402 398 return ret; 403 399 } 404 400
+7 -2
io_uring/poll.c
··· 272 272 atomic_andnot(IO_POLL_RETRY_FLAG, &req->poll_refs); 273 273 v &= ~IO_POLL_RETRY_FLAG; 274 274 } 275 + v &= IO_POLL_REF_MASK; 275 276 } 276 277 277 278 /* the mask was stashed in __io_poll_execute */ ··· 305 304 return IOU_POLL_REMOVE_POLL_USE_RES; 306 305 } 307 306 } else { 308 - int ret = io_poll_issue(req, tw); 307 + int ret; 309 308 309 + /* multiple refs and HUP, ensure we loop once more */ 310 + if ((req->cqe.res & (POLLHUP | POLLRDHUP)) && v != 1) 311 + v--; 312 + 313 + ret = io_poll_issue(req, tw); 310 314 if (ret == IOU_COMPLETE) 311 315 return IOU_POLL_REMOVE_POLL_USE_RES; 312 316 else if (ret == IOU_REQUEUE) ··· 327 321 * Release all references, retry if someone tried to restart 328 322 * task_work while we were executing it. 329 323 */ 330 - v &= IO_POLL_REF_MASK; 331 324 } while (atomic_sub_return(v, &req->poll_refs) & IO_POLL_REF_MASK); 332 325 333 326 io_napi_add(req);