Skip to content

Commit 7907f67

Browse files
committed
Merge tag 'io_uring-6.19-20260122' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux
Pull io_uring fixes from Jens Axboe: - Fix for a potential leak of an iovec, if a specific cleanup path is used and the rw_cache is full at the time of the call - Fix for a regression added in this cycle, where waitid should be using prober release/acquire semantics for updating the wait queue head - Check for the cancelation bit being set for every work item processed by io-wq, not just at the start of the loop. Has no real practical implications other than to shut up syzbot doing crazy things that grossly overload a system, hence slowing down ring exit - A few selftest additions, updating the mini_liburing that selftests use * tag 'io_uring-6.19-20260122' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux: selftests/io_uring: support NO_SQARRAY in miniliburing selftests/io_uring: add io_uring_queue_init_params io_uring/io-wq: check IO_WQ_BIT_EXIT inside work run loop io_uring/waitid: fix KCSAN warning on io_waitid->head io_uring/rw: free potentially allocated iovec on cache put failure
2 parents b33d706 + 145e007 commit 7907f67

4 files changed

Lines changed: 59 additions & 23 deletions

File tree

io_uring/io-wq.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -598,9 +598,9 @@ static void io_worker_handle_work(struct io_wq_acct *acct,
598598
__releases(&acct->lock)
599599
{
600600
struct io_wq *wq = worker->wq;
601-
bool do_kill = test_bit(IO_WQ_BIT_EXIT, &wq->state);
602601

603602
do {
603+
bool do_kill = test_bit(IO_WQ_BIT_EXIT, &wq->state);
604604
struct io_wq_work *work;
605605

606606
/*

io_uring/rw.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,19 +144,22 @@ static inline int io_import_rw_buffer(int rw, struct io_kiocb *req,
144144
return 0;
145145
}
146146

147-
static void io_rw_recycle(struct io_kiocb *req, unsigned int issue_flags)
147+
static bool io_rw_recycle(struct io_kiocb *req, unsigned int issue_flags)
148148
{
149149
struct io_async_rw *rw = req->async_data;
150150

151151
if (unlikely(issue_flags & IO_URING_F_UNLOCKED))
152-
return;
152+
return false;
153153

154154
io_alloc_cache_vec_kasan(&rw->vec);
155155
if (rw->vec.nr > IO_VEC_CACHE_SOFT_CAP)
156156
io_vec_free(&rw->vec);
157157

158-
if (io_alloc_cache_put(&req->ctx->rw_cache, rw))
158+
if (io_alloc_cache_put(&req->ctx->rw_cache, rw)) {
159159
io_req_async_data_clear(req, 0);
160+
return true;
161+
}
162+
return false;
160163
}
161164

162165
static void io_req_rw_cleanup(struct io_kiocb *req, unsigned int issue_flags)
@@ -190,7 +193,11 @@ static void io_req_rw_cleanup(struct io_kiocb *req, unsigned int issue_flags)
190193
*/
191194
if (!(req->flags & (REQ_F_REISSUE | REQ_F_REFCOUNT))) {
192195
req->flags &= ~REQ_F_NEED_CLEANUP;
193-
io_rw_recycle(req, issue_flags);
196+
if (!io_rw_recycle(req, issue_flags)) {
197+
struct io_async_rw *rw = req->async_data;
198+
199+
io_vec_free(&rw->vec);
200+
}
194201
}
195202
}
196203

io_uring/waitid.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,11 @@ static void io_waitid_remove_wq(struct io_kiocb *req)
114114
struct io_waitid *iw = io_kiocb_to_cmd(req, struct io_waitid);
115115
struct wait_queue_head *head;
116116

117-
head = READ_ONCE(iw->head);
117+
head = smp_load_acquire(&iw->head);
118118
if (head) {
119119
struct io_waitid_async *iwa = req->async_data;
120120

121-
iw->head = NULL;
121+
smp_store_release(&iw->head, NULL);
122122
spin_lock_irq(&head->lock);
123123
list_del_init(&iwa->wo.child_wait.entry);
124124
spin_unlock_irq(&head->lock);
@@ -246,7 +246,7 @@ static int io_waitid_wait(struct wait_queue_entry *wait, unsigned mode,
246246
return 0;
247247

248248
list_del_init(&wait->entry);
249-
iw->head = NULL;
249+
smp_store_release(&iw->head, NULL);
250250

251251
/* cancel is in progress */
252252
if (atomic_fetch_inc(&iw->refs) & IO_WAITID_REF_MASK)

tools/include/io_uring/mini_liburing.h

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <stdio.h>
77
#include <string.h>
88
#include <unistd.h>
9+
#include <sys/uio.h>
910

1011
struct io_sq_ring {
1112
unsigned int *head;
@@ -55,6 +56,7 @@ struct io_uring {
5556
struct io_uring_sq sq;
5657
struct io_uring_cq cq;
5758
int ring_fd;
59+
unsigned flags;
5860
};
5961

6062
#if defined(__x86_64) || defined(__i386__)
@@ -72,7 +74,14 @@ static inline int io_uring_mmap(int fd, struct io_uring_params *p,
7274
void *ptr;
7375
int ret;
7476

75-
sq->ring_sz = p->sq_off.array + p->sq_entries * sizeof(unsigned int);
77+
if (p->flags & IORING_SETUP_NO_SQARRAY) {
78+
sq->ring_sz = p->cq_off.cqes;
79+
sq->ring_sz += p->cq_entries * sizeof(struct io_uring_cqe);
80+
} else {
81+
sq->ring_sz = p->sq_off.array;
82+
sq->ring_sz += p->sq_entries * sizeof(unsigned int);
83+
}
84+
7685
ptr = mmap(0, sq->ring_sz, PROT_READ | PROT_WRITE,
7786
MAP_SHARED | MAP_POPULATE, fd, IORING_OFF_SQ_RING);
7887
if (ptr == MAP_FAILED)
@@ -83,7 +92,8 @@ static inline int io_uring_mmap(int fd, struct io_uring_params *p,
8392
sq->kring_entries = ptr + p->sq_off.ring_entries;
8493
sq->kflags = ptr + p->sq_off.flags;
8594
sq->kdropped = ptr + p->sq_off.dropped;
86-
sq->array = ptr + p->sq_off.array;
95+
if (!(p->flags & IORING_SETUP_NO_SQARRAY))
96+
sq->array = ptr + p->sq_off.array;
8797

8898
size = p->sq_entries * sizeof(struct io_uring_sqe);
8999
sq->sqes = mmap(0, size, PROT_READ | PROT_WRITE,
@@ -126,28 +136,39 @@ static inline int io_uring_enter(int fd, unsigned int to_submit,
126136
flags, sig, _NSIG / 8);
127137
}
128138

129-
static inline int io_uring_queue_init(unsigned int entries,
130-
struct io_uring *ring,
131-
unsigned int flags)
139+
static inline int io_uring_queue_init_params(unsigned int entries,
140+
struct io_uring *ring,
141+
struct io_uring_params *p)
132142
{
133-
struct io_uring_params p;
134143
int fd, ret;
135144

136145
memset(ring, 0, sizeof(*ring));
137-
memset(&p, 0, sizeof(p));
138-
p.flags = flags;
139146

140-
fd = io_uring_setup(entries, &p);
147+
fd = io_uring_setup(entries, p);
141148
if (fd < 0)
142149
return fd;
143-
ret = io_uring_mmap(fd, &p, &ring->sq, &ring->cq);
144-
if (!ret)
150+
ret = io_uring_mmap(fd, p, &ring->sq, &ring->cq);
151+
if (!ret) {
145152
ring->ring_fd = fd;
146-
else
153+
ring->flags = p->flags;
154+
} else {
147155
close(fd);
156+
}
148157
return ret;
149158
}
150159

160+
static inline int io_uring_queue_init(unsigned int entries,
161+
struct io_uring *ring,
162+
unsigned int flags)
163+
{
164+
struct io_uring_params p;
165+
166+
memset(&p, 0, sizeof(p));
167+
p.flags = flags;
168+
169+
return io_uring_queue_init_params(entries, ring, &p);
170+
}
171+
151172
/* Get a sqe */
152173
static inline struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring)
153174
{
@@ -199,10 +220,18 @@ static inline int io_uring_submit(struct io_uring *ring)
199220

200221
ktail = *sq->ktail;
201222
to_submit = sq->sqe_tail - sq->sqe_head;
202-
for (submitted = 0; submitted < to_submit; submitted++) {
203-
read_barrier();
204-
sq->array[ktail++ & mask] = sq->sqe_head++ & mask;
223+
224+
if (!(ring->flags & IORING_SETUP_NO_SQARRAY)) {
225+
for (submitted = 0; submitted < to_submit; submitted++) {
226+
read_barrier();
227+
sq->array[ktail++ & mask] = sq->sqe_head++ & mask;
228+
}
229+
} else {
230+
ktail += to_submit;
231+
sq->sqe_head += to_submit;
232+
submitted = to_submit;
205233
}
234+
206235
if (!submitted)
207236
return 0;
208237

0 commit comments

Comments
 (0)