Extract a helper io_uring_quiesce_ctx(), which takes care of ctx quiesce, it's complex enough. Signed-off-by: Pavel Begunkov <asml.silence@xxxxxxxxx> --- fs/io_uring.c | 52 ++++++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/fs/io_uring.c b/fs/io_uring.c index 3f764f2f2982..6e781c064e74 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -9683,6 +9683,33 @@ static bool io_register_op_must_quiesce(int op) } } +static int io_uring_quiesce_ctx(struct io_ring_ctx *ctx) +{ + int ret; + + percpu_ref_kill(&ctx->refs); + /* + * Drop uring mutex before waiting for references to exit. If + * another thread is currently inside io_uring_enter() it might + * need to grab the uring_lock to make progress. If we hold it + * here across the drain wait, then we can deadlock. It's safe + * to drop the mutex here, since no new references will come in + * after we've killed the percpu ref. + */ + mutex_unlock(&ctx->uring_lock); + do { + ret = wait_for_completion_interruptible(&ctx->ref_comp); + if (!ret) + break; + ret = io_run_task_work_sig(); + } while (ret >= 0); + mutex_lock(&ctx->uring_lock); + + if (ret && io_refs_resurrect(&ctx->refs, &ctx->ref_comp)) + return ret; + return 0; +} + static int __io_uring_register(struct io_ring_ctx *ctx, unsigned opcode, void __user *arg, unsigned nr_args) __releases(ctx->uring_lock) @@ -9699,29 +9726,8 @@ static int __io_uring_register(struct io_ring_ctx *ctx, unsigned opcode, return -ENXIO; if (io_register_op_must_quiesce(opcode)) { - percpu_ref_kill(&ctx->refs); - - /* - * Drop uring mutex before waiting for references to exit. If - * another thread is currently inside io_uring_enter() it might - * need to grab the uring_lock to make progress. If we hold it - * here across the drain wait, then we can deadlock. It's safe - * to drop the mutex here, since no new references will come in - * after we've killed the percpu ref. - */ - mutex_unlock(&ctx->uring_lock); - do { - ret = wait_for_completion_interruptible(&ctx->ref_comp); - if (!ret) - break; - ret = io_run_task_work_sig(); - if (ret < 0) - break; - } while (1); - - mutex_lock(&ctx->uring_lock); - - if (ret && io_refs_resurrect(&ctx->refs, &ctx->ref_comp)) + ret = io_uring_quiesce_ctx(ctx); + if (ret) return ret; } -- 2.24.0