On 04/02/2021 03:34, Hao Xu wrote: > 在 2021/2/4 上午12:33, Pavel Begunkov 写道: >> On 03/02/2021 14:57, Hao Xu wrote: >>> io_sqe_files_unregister is currently called from several places: >>> - syscall io_uring_register (with uring_lock) >>> - io_ring_ctx_wait_and_kill() (without uring_lock) >>> >>> There is a AA type deadlock in io_sqe_files_unregister(), thus we need >>> to know if we hold uring_lock in io_sqe_files_unregister() to fix the >>> issue. >> >> It's ugly, just take the lock and kill the patch. There can't be any >> contention during io_ring_ctx_free anyway. > Hi Pavel, I don't get it, do you mean this patch isn't needed, and we can just unlock(&uring_lock) before io_run_task_work_sig() and lock(&uring_lock) after it? I knew there won't be contention during io_ring_ctx_free that's why there is no uring_lock in it. > I tried to just do unlock(&uring_lock) before io_run_task_sig() without if(locked) check, it reports something like "there are unpaired mutex lock/unlock" since we cannot just unlock if it's from io_ring_ctx_free. The ugly part is @locked. I know that there is already similar stuff around, but I may go long why and how much I don't like it. io_ring_ctx_free() { ... lock(uring_lock); files_unregister(); unlock(uring_lock); ... } With this you'll always have the mutex locked in unregister, so can drop it unconditionally (if that will ever be needed). It's also cleaner from the synchronisation perspective. >> >>> >>> Signed-off-by: Hao Xu <haoxu@xxxxxxxxxxxxxxxxx> >>> --- >>> fs/io_uring.c | 10 +++++----- >>> 1 file changed, 5 insertions(+), 5 deletions(-) >>> >>> diff --git a/fs/io_uring.c b/fs/io_uring.c >>> index 38c6cbe1ab38..efb6d02fea6f 100644 >>> --- a/fs/io_uring.c >>> +++ b/fs/io_uring.c >>> @@ -7339,7 +7339,7 @@ static void io_sqe_files_set_node(struct fixed_file_data *file_data, >>> percpu_ref_get(&file_data->refs); >>> } >>> -static int io_sqe_files_unregister(struct io_ring_ctx *ctx) >>> +static int io_sqe_files_unregister(struct io_ring_ctx *ctx, bool locked) >>> { >>> struct fixed_file_data *data = ctx->file_data; >>> struct fixed_file_ref_node *backup_node, *ref_node = NULL; >>> @@ -7872,13 +7872,13 @@ static int io_sqe_files_register(struct io_ring_ctx *ctx, void __user *arg, >>> ret = io_sqe_files_scm(ctx); >>> if (ret) { >>> - io_sqe_files_unregister(ctx); >>> + io_sqe_files_unregister(ctx, true); >>> return ret; >>> } >>> ref_node = alloc_fixed_file_ref_node(ctx); >>> if (!ref_node) { >>> - io_sqe_files_unregister(ctx); >>> + io_sqe_files_unregister(ctx, true); >>> return -ENOMEM; >>> } >>> @@ -8682,7 +8682,7 @@ static void io_ring_ctx_free(struct io_ring_ctx *ctx) >>> css_put(ctx->sqo_blkcg_css); >>> #endif >>> - io_sqe_files_unregister(ctx); >>> + io_sqe_files_unregister(ctx, false); >>> io_eventfd_unregister(ctx); >>> io_destroy_buffers(ctx); >>> idr_destroy(&ctx->personality_idr); >>> @@ -10065,7 +10065,7 @@ static int __io_uring_register(struct io_ring_ctx *ctx, unsigned opcode, >>> ret = -EINVAL; >>> if (arg || nr_args) >>> break; >>> - ret = io_sqe_files_unregister(ctx); >>> + ret = io_sqe_files_unregister(ctx, true); >>> break; >>> case IORING_REGISTER_FILES_UPDATE: >>> ret = io_sqe_files_update(ctx, arg, nr_args); >>> >> > -- Pavel Begunkov