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.13-20250116' of git://git.kernel.dk/linux

Pull io_uring fixes from Jens Axboe:
"One fix for the error handling in buffer cloning, and one fix for the
ring resizing.

Two minor followups for the latter as well.

Both of these issues only affect 6.13, so not marked for stable"

* tag 'io_uring-6.13-20250116' of git://git.kernel.dk/linux:
io_uring/register: cache old SQ/CQ head reading for copies
io_uring/register: document io_register_resize_rings() shared mem usage
io_uring/register: use stable SQ/CQ ring data during resize
io_uring/rsrc: fixup io_clone_buffers() error handling

+32 -30
+31 -21
io_uring/register.c
··· 405 405 { 406 406 struct io_ring_ctx_rings o = { }, n = { }, *to_free = NULL; 407 407 size_t size, sq_array_offset; 408 + unsigned i, tail, old_head; 408 409 struct io_uring_params p; 409 - unsigned i, tail; 410 410 void *ptr; 411 411 int ret; 412 412 ··· 449 449 if (IS_ERR(n.rings)) 450 450 return PTR_ERR(n.rings); 451 451 452 - n.rings->sq_ring_mask = p.sq_entries - 1; 453 - n.rings->cq_ring_mask = p.cq_entries - 1; 454 - n.rings->sq_ring_entries = p.sq_entries; 455 - n.rings->cq_ring_entries = p.cq_entries; 452 + /* 453 + * At this point n.rings is shared with userspace, just like o.rings 454 + * is as well. While we don't expect userspace to modify it while 455 + * a resize is in progress, and it's most likely that userspace will 456 + * shoot itself in the foot if it does, we can't always assume good 457 + * intent... Use read/write once helpers from here on to indicate the 458 + * shared nature of it. 459 + */ 460 + WRITE_ONCE(n.rings->sq_ring_mask, p.sq_entries - 1); 461 + WRITE_ONCE(n.rings->cq_ring_mask, p.cq_entries - 1); 462 + WRITE_ONCE(n.rings->sq_ring_entries, p.sq_entries); 463 + WRITE_ONCE(n.rings->cq_ring_entries, p.cq_entries); 456 464 457 465 if (copy_to_user(arg, &p, sizeof(p))) { 458 466 io_register_free_rings(&p, &n); ··· 517 509 * rings can't hold what is already there, then fail the operation. 518 510 */ 519 511 n.sq_sqes = ptr; 520 - tail = o.rings->sq.tail; 521 - if (tail - o.rings->sq.head > p.sq_entries) 512 + tail = READ_ONCE(o.rings->sq.tail); 513 + old_head = READ_ONCE(o.rings->sq.head); 514 + if (tail - old_head > p.sq_entries) 522 515 goto overflow; 523 - for (i = o.rings->sq.head; i < tail; i++) { 516 + for (i = old_head; i < tail; i++) { 524 517 unsigned src_head = i & (ctx->sq_entries - 1); 525 - unsigned dst_head = i & n.rings->sq_ring_mask; 518 + unsigned dst_head = i & (p.sq_entries - 1); 526 519 527 520 n.sq_sqes[dst_head] = o.sq_sqes[src_head]; 528 521 } 529 - n.rings->sq.head = o.rings->sq.head; 530 - n.rings->sq.tail = o.rings->sq.tail; 522 + WRITE_ONCE(n.rings->sq.head, READ_ONCE(o.rings->sq.head)); 523 + WRITE_ONCE(n.rings->sq.tail, READ_ONCE(o.rings->sq.tail)); 531 524 532 - tail = o.rings->cq.tail; 533 - if (tail - o.rings->cq.head > p.cq_entries) { 525 + tail = READ_ONCE(o.rings->cq.tail); 526 + old_head = READ_ONCE(o.rings->cq.head); 527 + if (tail - old_head > p.cq_entries) { 534 528 overflow: 535 529 /* restore old rings, and return -EOVERFLOW via cleanup path */ 536 530 ctx->rings = o.rings; ··· 541 531 ret = -EOVERFLOW; 542 532 goto out; 543 533 } 544 - for (i = o.rings->cq.head; i < tail; i++) { 534 + for (i = old_head; i < tail; i++) { 545 535 unsigned src_head = i & (ctx->cq_entries - 1); 546 - unsigned dst_head = i & n.rings->cq_ring_mask; 536 + unsigned dst_head = i & (p.cq_entries - 1); 547 537 548 538 n.rings->cqes[dst_head] = o.rings->cqes[src_head]; 549 539 } 550 - n.rings->cq.head = o.rings->cq.head; 551 - n.rings->cq.tail = o.rings->cq.tail; 540 + WRITE_ONCE(n.rings->cq.head, READ_ONCE(o.rings->cq.head)); 541 + WRITE_ONCE(n.rings->cq.tail, READ_ONCE(o.rings->cq.tail)); 552 542 /* invalidate cached cqe refill */ 553 543 ctx->cqe_cached = ctx->cqe_sentinel = NULL; 554 544 555 - n.rings->sq_dropped = o.rings->sq_dropped; 556 - n.rings->sq_flags = o.rings->sq_flags; 557 - n.rings->cq_flags = o.rings->cq_flags; 558 - n.rings->cq_overflow = o.rings->cq_overflow; 545 + WRITE_ONCE(n.rings->sq_dropped, READ_ONCE(o.rings->sq_dropped)); 546 + WRITE_ONCE(n.rings->sq_flags, READ_ONCE(o.rings->sq_flags)); 547 + WRITE_ONCE(n.rings->cq_flags, READ_ONCE(o.rings->cq_flags)); 548 + WRITE_ONCE(n.rings->cq_overflow, READ_ONCE(o.rings->cq_overflow)); 559 549 560 550 /* all done, store old pointers and assign new ones */ 561 551 if (!(ctx->flags & IORING_SETUP_NO_SQARRAY))
+1 -9
io_uring/rsrc.c
··· 997 997 dst_node = io_rsrc_node_alloc(ctx, IORING_RSRC_BUFFER); 998 998 if (!dst_node) { 999 999 ret = -ENOMEM; 1000 - goto out_put_free; 1000 + goto out_unlock; 1001 1001 } 1002 1002 1003 1003 refcount_inc(&src_node->buf->refs); ··· 1033 1033 mutex_lock(&src_ctx->uring_lock); 1034 1034 /* someone raced setting up buffers, dump ours */ 1035 1035 ret = -EBUSY; 1036 - out_put_free: 1037 - i = data.nr; 1038 - while (i--) { 1039 - if (data.nodes[i]) { 1040 - io_buffer_unmap(src_ctx, data.nodes[i]); 1041 - kfree(data.nodes[i]); 1042 - } 1043 - } 1044 1036 out_unlock: 1045 1037 io_rsrc_data_free(ctx, &data); 1046 1038 mutex_unlock(&src_ctx->uring_lock);