提交 cb5e1b81 编写于 作者: J Jens Axboe

Revert "io_uring: wait potential ->release() on resurrect"

This reverts commit 88f171ab.

I ran into a case where the ref resurrect now spins, so revert
this change for now until we can further investigate why it's
broken. The bug seems to indicate spinning on the lock itself,
likely there's some ABBA deadlock involved:

[<0>] __percpu_ref_switch_mode+0x45/0x180
[<0>] percpu_ref_resurrect+0x46/0x70
[<0>] io_refs_resurrect+0x25/0xa0
[<0>] __io_uring_register+0x135/0x10c0
[<0>] __x64_sys_io_uring_register+0xc2/0x1a0
[<0>] do_syscall_64+0x42/0x110
[<0>] entry_SYSCALL_64_after_hwframe+0x44/0xa9
Signed-off-by: NJens Axboe <axboe@kernel.dk>
上级 e5547d2c
......@@ -1104,21 +1104,6 @@ static inline void io_set_resource_node(struct io_kiocb *req)
}
}
static bool io_refs_resurrect(struct percpu_ref *ref, struct completion *compl)
{
if (!percpu_ref_tryget(ref)) {
/* already at zero, wait for ->release() */
if (!try_wait_for_completion(compl))
synchronize_rcu();
return false;
}
percpu_ref_resurrect(ref);
reinit_completion(compl);
percpu_ref_put(ref);
return true;
}
static bool io_match_task(struct io_kiocb *head,
struct task_struct *task,
struct files_struct *files)
......@@ -7353,11 +7338,13 @@ static int io_rsrc_ref_quiesce(struct fixed_rsrc_data *data,
flush_delayed_work(&ctx->rsrc_put_work);
ret = wait_for_completion_interruptible(&data->done);
if (!ret || !io_refs_resurrect(&data->refs, &data->done))
if (!ret)
break;
percpu_ref_resurrect(&data->refs);
io_sqe_rsrc_set_node(ctx, data, backup_node);
backup_node = NULL;
reinit_completion(&data->done);
mutex_unlock(&ctx->uring_lock);
ret = io_run_task_work_sig();
mutex_lock(&ctx->uring_lock);
......@@ -10096,8 +10083,10 @@ static int __io_uring_register(struct io_ring_ctx *ctx, unsigned opcode,
mutex_lock(&ctx->uring_lock);
if (ret && io_refs_resurrect(&ctx->refs, &ctx->ref_comp))
return ret;
if (ret) {
percpu_ref_resurrect(&ctx->refs);
goto out_quiesce;
}
}
if (ctx->restricted) {
......@@ -10189,6 +10178,7 @@ static int __io_uring_register(struct io_ring_ctx *ctx, unsigned opcode,
if (io_register_op_must_quiesce(opcode)) {
/* bring the ctx back to life */
percpu_ref_reinit(&ctx->refs);
out_quiesce:
reinit_completion(&ctx->ref_comp);
}
return ret;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册