Skip to content

Commit 52ea806

Browse files
committed
io_uring: finish waiting before flushing overflow entries
If we have overflow entries being generated after we've done the initial flush in io_cqring_wait(), then we could be flushing them in the main wait loop as well. If that's done after having added ourselves to the cq_wait waitqueue, then the task state can be != TASK_RUNNING when we enter the overflow flush. Check for the need to overflow flush, and finish our wait cycle first if we have to do so. Reported-and-tested-by: [email protected] Link: https://lore.kernel.org/io-uring/[email protected]/ Signed-off-by: Jens Axboe <[email protected]>
1 parent 5ad70eb commit 52ea806

File tree

1 file changed

+16
-9
lines changed

1 file changed

+16
-9
lines changed

io_uring/io_uring.c

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -677,16 +677,20 @@ static void __io_cqring_overflow_flush(struct io_ring_ctx *ctx)
677677
io_cq_unlock_post(ctx);
678678
}
679679

680+
static void io_cqring_do_overflow_flush(struct io_ring_ctx *ctx)
681+
{
682+
/* iopoll syncs against uring_lock, not completion_lock */
683+
if (ctx->flags & IORING_SETUP_IOPOLL)
684+
mutex_lock(&ctx->uring_lock);
685+
__io_cqring_overflow_flush(ctx);
686+
if (ctx->flags & IORING_SETUP_IOPOLL)
687+
mutex_unlock(&ctx->uring_lock);
688+
}
689+
680690
static void io_cqring_overflow_flush(struct io_ring_ctx *ctx)
681691
{
682-
if (test_bit(IO_CHECK_CQ_OVERFLOW_BIT, &ctx->check_cq)) {
683-
/* iopoll syncs against uring_lock, not completion_lock */
684-
if (ctx->flags & IORING_SETUP_IOPOLL)
685-
mutex_lock(&ctx->uring_lock);
686-
__io_cqring_overflow_flush(ctx);
687-
if (ctx->flags & IORING_SETUP_IOPOLL)
688-
mutex_unlock(&ctx->uring_lock);
689-
}
692+
if (test_bit(IO_CHECK_CQ_OVERFLOW_BIT, &ctx->check_cq))
693+
io_cqring_do_overflow_flush(ctx);
690694
}
691695

692696
void __io_put_task(struct task_struct *task, int nr)
@@ -2549,7 +2553,10 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events,
25492553

25502554
trace_io_uring_cqring_wait(ctx, min_events);
25512555
do {
2552-
io_cqring_overflow_flush(ctx);
2556+
if (test_bit(IO_CHECK_CQ_OVERFLOW_BIT, &ctx->check_cq)) {
2557+
finish_wait(&ctx->cq_wait, &iowq.wq);
2558+
io_cqring_do_overflow_flush(ctx);
2559+
}
25532560
prepare_to_wait_exclusive(&ctx->cq_wait, &iowq.wq,
25542561
TASK_INTERRUPTIBLE);
25552562
ret = io_cqring_wait_schedule(ctx, &iowq, timeout);

0 commit comments

Comments
 (0)