From 308571debccd7004acf02ea1b7163a96ad772292 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Tue, 18 Aug 2020 15:05:19 +0300 Subject: [PATCH] RDMA/ucma: Do not use file->mut to lock destroying The only reader of destroying is inside a handler under the handler_mutex, so directly use the handler_mutex when setting it instead of the larger file->mut. As the refcount could be zero here, and the cm_id already freed, and additional refcount grab around the locking is required to touch the cm_id. Link: https://lore.kernel.org/r/20200818120526.702120-8-leon@kernel.org Signed-off-by: Leon Romanovsky Signed-off-by: Jason Gunthorpe --- drivers/infiniband/core/ucma.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c index add1ece38739..18285941aec3 100644 --- a/drivers/infiniband/core/ucma.c +++ b/drivers/infiniband/core/ucma.c @@ -602,9 +602,17 @@ static int ucma_free_ctx(struct ucma_context *ctx) static int __destroy_id(struct ucma_context *ctx) { - mutex_lock(&ctx->file->mut); - ctx->destroying = 1; - mutex_unlock(&ctx->file->mut); + /* + * If the refcount is already 0 then ucma_close_id() has already + * destroyed the cm_id, otherwise holding the refcount keeps cm_id + * valid. Prevent queue_work() from being called. + */ + if (refcount_inc_not_zero(&ctx->ref)) { + rdma_lock_handler(ctx->cm_id); + ctx->destroying = 1; + rdma_unlock_handler(ctx->cm_id); + ucma_put_ctx(ctx); + } flush_workqueue(ctx->file->close_wq); /* At this point it's guaranteed that there is no inflight closing task */ -- 2.39.5