Commit e54945ae authored by Jens Axboe's avatar Jens Axboe

io_uring: SQPOLL stop error handling fixes

If we fail to fork an SQPOLL worker, we can hit cancel, and hence
attempted thread stop, with the thread already being stopped. Ensure
we check for that.

Also guard thread stop fully by the sqd mutex, just like we do for
park.
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 470ec4ed
...@@ -6793,9 +6793,9 @@ static int io_sq_thread(void *data) ...@@ -6793,9 +6793,9 @@ static int io_sq_thread(void *data)
ctx->sqo_exec = 1; ctx->sqo_exec = 1;
io_ring_set_wakeup_flag(ctx); io_ring_set_wakeup_flag(ctx);
} }
mutex_unlock(&sqd->lock);
complete(&sqd->exited); complete(&sqd->exited);
mutex_unlock(&sqd->lock);
do_exit(0); do_exit(0);
} }
...@@ -7118,13 +7118,19 @@ static bool io_sq_thread_park(struct io_sq_data *sqd) ...@@ -7118,13 +7118,19 @@ static bool io_sq_thread_park(struct io_sq_data *sqd)
static void io_sq_thread_stop(struct io_sq_data *sqd) static void io_sq_thread_stop(struct io_sq_data *sqd)
{ {
if (!sqd->thread) if (test_bit(IO_SQ_THREAD_SHOULD_STOP, &sqd->state))
return; return;
mutex_lock(&sqd->lock);
set_bit(IO_SQ_THREAD_SHOULD_STOP, &sqd->state); if (sqd->thread) {
WARN_ON_ONCE(test_bit(IO_SQ_THREAD_SHOULD_PARK, &sqd->state)); set_bit(IO_SQ_THREAD_SHOULD_STOP, &sqd->state);
wake_up_process(sqd->thread); WARN_ON_ONCE(test_bit(IO_SQ_THREAD_SHOULD_PARK, &sqd->state));
wait_for_completion(&sqd->exited); wake_up_process(sqd->thread);
mutex_unlock(&sqd->lock);
wait_for_completion(&sqd->exited);
WARN_ON_ONCE(sqd->thread);
} else {
mutex_unlock(&sqd->lock);
}
} }
static void io_put_sq_data(struct io_sq_data *sqd) static void io_put_sq_data(struct io_sq_data *sqd)
...@@ -8867,6 +8873,11 @@ static void io_uring_cancel_sqpoll(struct io_ring_ctx *ctx) ...@@ -8867,6 +8873,11 @@ static void io_uring_cancel_sqpoll(struct io_ring_ctx *ctx)
if (!io_sq_thread_park(sqd)) if (!io_sq_thread_park(sqd))
return; return;
tctx = ctx->sq_data->thread->io_uring; tctx = ctx->sq_data->thread->io_uring;
/* can happen on fork/alloc failure, just ignore that state */
if (!tctx) {
io_sq_thread_unpark(sqd);
return;
}
atomic_inc(&tctx->in_idle); atomic_inc(&tctx->in_idle);
do { do {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment