summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJens Axboe <axboe@kernel.dk>2021-03-09 16:32:13 -0700
committerJens Axboe <axboe@kernel.dk>2021-03-10 07:28:43 -0700
commite8f98f24549d62cc54bf608c815904a56d4437bc (patch)
treea545de836d886a769bd0c68c3df1248e1c15135c /fs
parent5199328a0d415b3e372633096b1b92f36b8ac9e5 (diff)
downloadlinux-e8f98f24549d62cc54bf608c815904a56d4437bc.tar.gz
linux-e8f98f24549d62cc54bf608c815904a56d4437bc.tar.bz2
linux-e8f98f24549d62cc54bf608c815904a56d4437bc.zip
io_uring: always wait for sqd exited when stopping SQPOLL thread
We have a tiny race where io_put_sq_data() calls io_sq_thead_stop() and finds the thread gone, but the thread has indeed not fully exited or called complete() yet. Close it up by always having io_sq_thread_stop() wait on completion of the exit event. Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'fs')
-rw-r--r--fs/io_uring.c16
1 files changed, 8 insertions, 8 deletions
diff --git a/fs/io_uring.c b/fs/io_uring.c
index 6325f32ef6a3..62f998bf2ce8 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -7079,12 +7079,9 @@ static void io_sq_thread_stop(struct io_sq_data *sqd)
if (test_bit(IO_SQ_THREAD_SHOULD_STOP, &sqd->state))
return;
down_write(&sqd->rw_lock);
- if (!sqd->thread) {
- up_write(&sqd->rw_lock);
- return;
- }
set_bit(IO_SQ_THREAD_SHOULD_STOP, &sqd->state);
- wake_up_process(sqd->thread);
+ if (sqd->thread)
+ wake_up_process(sqd->thread);
up_write(&sqd->rw_lock);
wait_for_completion(&sqd->exited);
}
@@ -7849,9 +7846,9 @@ static int io_sq_offload_create(struct io_ring_ctx *ctx,
ret = -EINVAL;
if (cpu >= nr_cpu_ids)
- goto err;
+ goto err_sqpoll;
if (!cpu_online(cpu))
- goto err;
+ goto err_sqpoll;
sqd->sq_cpu = cpu;
} else {
@@ -7862,7 +7859,7 @@ static int io_sq_offload_create(struct io_ring_ctx *ctx,
tsk = create_io_thread(io_sq_thread, sqd, NUMA_NO_NODE);
if (IS_ERR(tsk)) {
ret = PTR_ERR(tsk);
- goto err;
+ goto err_sqpoll;
}
sqd->thread = tsk;
@@ -7881,6 +7878,9 @@ static int io_sq_offload_create(struct io_ring_ctx *ctx,
err:
io_sq_thread_finish(ctx);
return ret;
+err_sqpoll:
+ complete(&ctx->sq_data->exited);
+ goto err;
}
static inline void __io_unaccount_mem(struct user_struct *user,