Skip to content

Commit 4e6b2b2

Browse files
committed
Merge tag 'io_uring-6.1-2022-11-11' of git://git.kernel.dk/linux
Pull io_uring fixes from Jens Axboe: "Nothing major, just a few minor tweaks: - Tweak for the TCP zero-copy io_uring self test (Pavel) - Rather than use our internal cached value of number of CQ events available, use what the user can see (Dylan) - Fix a typo in a comment, added in this release (me) - Don't allow wrapping while adding provided buffers (me) - Fix a double poll race, and add a lockdep assertion for it too (Pavel)" * tag 'io_uring-6.1-2022-11-11' of git://git.kernel.dk/linux: io_uring/poll: lockdep annote io_poll_req_insert_locked io_uring/poll: fix double poll req->flags races io_uring: check for rollover of buffer ID when providing buffers io_uring: calculate CQEs from the user visible value io_uring: fix typo in io_uring.h comment selftests/net: don't tests batched TCP io_uring zc
2 parents f5020a0 + 5576035 commit 4e6b2b2

File tree

5 files changed

+31
-16
lines changed

5 files changed

+31
-16
lines changed

include/uapi/linux/io_uring.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ enum io_uring_op {
222222

223223
/*
224224
* sqe->uring_cmd_flags
225-
* IORING_URING_CMD_FIXED use registered buffer; pass thig flag
225+
* IORING_URING_CMD_FIXED use registered buffer; pass this flag
226226
* along with setting sqe->buf_index.
227227
*/
228228
#define IORING_URING_CMD_FIXED (1U << 0)

io_uring/io_uring.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,11 @@ static inline unsigned int __io_cqring_events(struct io_ring_ctx *ctx)
176176
return ctx->cached_cq_tail - READ_ONCE(ctx->rings->cq.head);
177177
}
178178

179+
static inline unsigned int __io_cqring_events_user(struct io_ring_ctx *ctx)
180+
{
181+
return READ_ONCE(ctx->rings->cq.tail) - READ_ONCE(ctx->rings->cq.head);
182+
}
183+
179184
static bool io_match_linked(struct io_kiocb *head)
180185
{
181186
struct io_kiocb *req;
@@ -2315,7 +2320,7 @@ static inline bool io_has_work(struct io_ring_ctx *ctx)
23152320
static inline bool io_should_wake(struct io_wait_queue *iowq)
23162321
{
23172322
struct io_ring_ctx *ctx = iowq->ctx;
2318-
int dist = ctx->cached_cq_tail - (int) iowq->cq_tail;
2323+
int dist = READ_ONCE(ctx->rings->cq.tail) - (int) iowq->cq_tail;
23192324

23202325
/*
23212326
* Wake up if we have enough events, or if a timeout occurred since we
@@ -2399,7 +2404,8 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events,
23992404
return ret;
24002405
io_cqring_overflow_flush(ctx);
24012406

2402-
if (io_cqring_events(ctx) >= min_events)
2407+
/* if user messes with these they will just get an early return */
2408+
if (__io_cqring_events_user(ctx) >= min_events)
24032409
return 0;
24042410
} while (ret > 0);
24052411

io_uring/kbuf.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,8 @@ int io_provide_buffers_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe
346346
tmp = READ_ONCE(sqe->off);
347347
if (tmp > USHRT_MAX)
348348
return -E2BIG;
349+
if (tmp + p->nbufs >= USHRT_MAX)
350+
return -EINVAL;
349351
p->bid = tmp;
350352
return 0;
351353
}

io_uring/poll.c

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ static void io_poll_req_insert_locked(struct io_kiocb *req)
116116
struct io_hash_table *table = &req->ctx->cancel_table_locked;
117117
u32 index = hash_long(req->cqe.user_data, table->hash_bits);
118118

119+
lockdep_assert_held(&req->ctx->uring_lock);
120+
119121
hlist_add_head(&req->hash_node, &table->hbs[index].list);
120122
}
121123

@@ -394,7 +396,8 @@ static int io_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync,
394396
return 1;
395397
}
396398

397-
static void io_poll_double_prepare(struct io_kiocb *req)
399+
/* fails only when polling is already completing by the first entry */
400+
static bool io_poll_double_prepare(struct io_kiocb *req)
398401
{
399402
struct wait_queue_head *head;
400403
struct io_poll *poll = io_poll_get_single(req);
@@ -403,20 +406,20 @@ static void io_poll_double_prepare(struct io_kiocb *req)
403406
rcu_read_lock();
404407
head = smp_load_acquire(&poll->head);
405408
/*
406-
* poll arm may not hold ownership and so race with
407-
* io_poll_wake() by modifying req->flags. There is only one
408-
* poll entry queued, serialise with it by taking its head lock.
409+
* poll arm might not hold ownership and so race for req->flags with
410+
* io_poll_wake(). There is only one poll entry queued, serialise with
411+
* it by taking its head lock. As we're still arming the tw hanlder
412+
* is not going to be run, so there are no races with it.
409413
*/
410-
if (head)
414+
if (head) {
411415
spin_lock_irq(&head->lock);
412-
413-
req->flags |= REQ_F_DOUBLE_POLL;
414-
if (req->opcode == IORING_OP_POLL_ADD)
415-
req->flags |= REQ_F_ASYNC_DATA;
416-
417-
if (head)
416+
req->flags |= REQ_F_DOUBLE_POLL;
417+
if (req->opcode == IORING_OP_POLL_ADD)
418+
req->flags |= REQ_F_ASYNC_DATA;
418419
spin_unlock_irq(&head->lock);
420+
}
419421
rcu_read_unlock();
422+
return !!head;
420423
}
421424

422425
static void __io_queue_proc(struct io_poll *poll, struct io_poll_table *pt,
@@ -454,7 +457,11 @@ static void __io_queue_proc(struct io_poll *poll, struct io_poll_table *pt,
454457
/* mark as double wq entry */
455458
wqe_private |= IO_WQE_F_DOUBLE;
456459
io_init_poll_iocb(poll, first->events, first->wait.func);
457-
io_poll_double_prepare(req);
460+
if (!io_poll_double_prepare(req)) {
461+
/* the request is completing, just back off */
462+
kfree(poll);
463+
return;
464+
}
458465
*poll_ptr = poll;
459466
} else {
460467
/* fine to modify, there is no poll queued to race with us */

tools/testing/selftests/net/io_uring_zerocopy_tx.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ if [[ "$#" -eq "0" ]]; then
2929
for IP in "${IPs[@]}"; do
3030
for mode in $(seq 1 3); do
3131
$0 "$IP" udp -m "$mode" -t 1 -n 32
32-
$0 "$IP" tcp -m "$mode" -t 1 -n 32
32+
$0 "$IP" tcp -m "$mode" -t 1 -n 1
3333
done
3434
done
3535

0 commit comments

Comments
 (0)