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

Pull io_uring fixes from Jens Axboe:

- Fix an issue with the read multishot support and posting of CQEs from
io-wq context

- Fix a regression introduced in this cycle, where making the timeout
lock a raw one uncovered another locking dependency. As a result,
move the timeout flushing outside of the timeout lock, punting them
to a local list first

- Fix use of an uninitialized variable in io_async_msghdr. Doesn't
really matter functionally, but silences a valid KMSAN complaint that
it's not always initialized

- Fix use of incrementally provided buffers for read on non-pollable
files, where the buffer always gets committed upfront. Unfortunately
the buffer address isn't resolved first, so the read ends up using
the updated rather than the current value

* tag 'io_uring-6.13-20250103' of git://git.kernel.dk/linux:
io_uring/kbuf: use pre-committed buffer address for non-pollable file
io_uring/net: always initialize kmsg->msg.msg_inq upfront
io_uring/timeout: flush timeouts outside of the timeout lock
io_uring/rw: fix downgraded mshot read

+37 -15
+3 -1
io_uring/kbuf.c
··· 139 139 struct io_uring_buf_ring *br = bl->buf_ring; 140 140 __u16 tail, head = bl->head; 141 141 struct io_uring_buf *buf; 142 + void __user *ret; 142 143 143 144 tail = smp_load_acquire(&br->tail); 144 145 if (unlikely(tail == head)) ··· 154 153 req->flags |= REQ_F_BUFFER_RING | REQ_F_BUFFERS_COMMIT; 155 154 req->buf_list = bl; 156 155 req->buf_index = buf->bid; 156 + ret = u64_to_user_ptr(buf->addr); 157 157 158 158 if (issue_flags & IO_URING_F_UNLOCKED || !io_file_can_poll(req)) { 159 159 /* ··· 170 168 io_kbuf_commit(req, bl, *len, 1); 171 169 req->buf_list = NULL; 172 170 } 173 - return u64_to_user_ptr(buf->addr); 171 + return ret; 174 172 } 175 173 176 174 void __user *io_buffer_select(struct io_kiocb *req, size_t *len,
+1
io_uring/net.c
··· 754 754 if (req->opcode == IORING_OP_RECV) { 755 755 kmsg->msg.msg_name = NULL; 756 756 kmsg->msg.msg_namelen = 0; 757 + kmsg->msg.msg_inq = 0; 757 758 kmsg->msg.msg_control = NULL; 758 759 kmsg->msg.msg_get_inq = 1; 759 760 kmsg->msg.msg_controllen = 0;
+2
io_uring/rw.c
··· 983 983 io_kbuf_recycle(req, issue_flags); 984 984 if (ret < 0) 985 985 req_set_fail(req); 986 + } else if (!(req->flags & REQ_F_APOLL_MULTISHOT)) { 987 + cflags = io_put_kbuf(req, ret, issue_flags); 986 988 } else { 987 989 /* 988 990 * Any successful return value will keep the multishot read
+31 -14
io_uring/timeout.c
··· 85 85 io_req_task_complete(req, ts); 86 86 } 87 87 88 - static bool io_kill_timeout(struct io_kiocb *req, int status) 88 + static __cold bool io_flush_killed_timeouts(struct list_head *list, int err) 89 + { 90 + if (list_empty(list)) 91 + return false; 92 + 93 + while (!list_empty(list)) { 94 + struct io_timeout *timeout; 95 + struct io_kiocb *req; 96 + 97 + timeout = list_first_entry(list, struct io_timeout, list); 98 + list_del_init(&timeout->list); 99 + req = cmd_to_io_kiocb(timeout); 100 + if (err) 101 + req_set_fail(req); 102 + io_req_queue_tw_complete(req, err); 103 + } 104 + 105 + return true; 106 + } 107 + 108 + static void io_kill_timeout(struct io_kiocb *req, struct list_head *list) 89 109 __must_hold(&req->ctx->timeout_lock) 90 110 { 91 111 struct io_timeout_data *io = req->async_data; ··· 113 93 if (hrtimer_try_to_cancel(&io->timer) != -1) { 114 94 struct io_timeout *timeout = io_kiocb_to_cmd(req, struct io_timeout); 115 95 116 - if (status) 117 - req_set_fail(req); 118 96 atomic_set(&req->ctx->cq_timeouts, 119 97 atomic_read(&req->ctx->cq_timeouts) + 1); 120 - list_del_init(&timeout->list); 121 - io_req_queue_tw_complete(req, status); 122 - return true; 98 + list_move_tail(&timeout->list, list); 123 99 } 124 - return false; 125 100 } 126 101 127 102 __cold void io_flush_timeouts(struct io_ring_ctx *ctx) 128 103 { 129 - u32 seq; 130 104 struct io_timeout *timeout, *tmp; 105 + LIST_HEAD(list); 106 + u32 seq; 131 107 132 108 raw_spin_lock_irq(&ctx->timeout_lock); 133 109 seq = ctx->cached_cq_tail - atomic_read(&ctx->cq_timeouts); ··· 147 131 if (events_got < events_needed) 148 132 break; 149 133 150 - io_kill_timeout(req, 0); 134 + io_kill_timeout(req, &list); 151 135 } 152 136 ctx->cq_last_tm_flush = seq; 153 137 raw_spin_unlock_irq(&ctx->timeout_lock); 138 + io_flush_killed_timeouts(&list, 0); 154 139 } 155 140 156 141 static void io_req_tw_fail_links(struct io_kiocb *link, struct io_tw_state *ts) ··· 678 661 bool cancel_all) 679 662 { 680 663 struct io_timeout *timeout, *tmp; 681 - int canceled = 0; 664 + LIST_HEAD(list); 682 665 683 666 /* 684 667 * completion_lock is needed for io_match_task(). Take it before ··· 689 672 list_for_each_entry_safe(timeout, tmp, &ctx->timeout_list, list) { 690 673 struct io_kiocb *req = cmd_to_io_kiocb(timeout); 691 674 692 - if (io_match_task(req, tctx, cancel_all) && 693 - io_kill_timeout(req, -ECANCELED)) 694 - canceled++; 675 + if (io_match_task(req, tctx, cancel_all)) 676 + io_kill_timeout(req, &list); 695 677 } 696 678 raw_spin_unlock_irq(&ctx->timeout_lock); 697 679 spin_unlock(&ctx->completion_lock); 698 - return canceled != 0; 680 + 681 + return io_flush_killed_timeouts(&list, -ECANCELED); 699 682 }