summaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/core/ucma.c
diff options
context:
space:
mode:
authorJason Gunthorpe <jgg@nvidia.com>2020-08-18 14:05:19 +0200
committerJason Gunthorpe <jgg@nvidia.com>2020-08-27 13:38:15 +0200
commit308571debccd7004acf02ea1b7163a96ad772292 (patch)
tree75134da6d7a03c9d5fc4ed96eb7bad0de2f5c42c /drivers/infiniband/core/ucma.c
parentRDMA/cma: Add missing locking to rdma_accept() (diff)
downloadlinux-308571debccd7004acf02ea1b7163a96ad772292.tar.xz
linux-308571debccd7004acf02ea1b7163a96ad772292.zip
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 <leonro@mellanox.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Diffstat (limited to 'drivers/infiniband/core/ucma.c')
-rw-r--r--drivers/infiniband/core/ucma.c14
1 files 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 */