RDMA/ucma: Do not use file->mut to lock destroying
authorJason Gunthorpe <jgg@nvidia.com>
Tue, 18 Aug 2020 12:05:19 +0000 (15:05 +0300)
committerJason Gunthorpe <jgg@nvidia.com>
Thu, 27 Aug 2020 11:38:15 +0000 (08:38 -0300)
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 <leonro@mellanox.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
drivers/infiniband/core/ucma.c

index add1ece38739fec61efeec74cba9beedc12e27fc..18285941aec3d7c4ca05cbd1215c67242654ba35 100644 (file)
@@ -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 */