summaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/core/cm.c
diff options
context:
space:
mode:
authorJason Gunthorpe <jgg@mellanox.com>2020-03-10 11:25:34 +0200
committerJason Gunthorpe <jgg@mellanox.com>2020-03-17 17:05:52 -0300
commit2305d6864aa54c1887563d9096e4b746bc776d04 (patch)
treeb1a3e48ada37c1dd668d8a146be805948c3b6a0e /drivers/infiniband/core/cm.c
parentbede86a39d9dc3387ac00dcb8e1ac221676b2f25 (diff)
downloadlinux-2305d6864aa54c1887563d9096e4b746bc776d04.tar.bz2
RDMA/cm: Make the destroy_id flow more robust
Too much of the destruction is very carefully sensitive to the state and various other things. Move more code to the unconditional path and add several WARN_ONs to check consistency. Link: https://lore.kernel.org/r/20200310092545.251365-5-leon@kernel.org Signed-off-by: Leon Romanovsky <leonro@mellanox.com> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
Diffstat (limited to 'drivers/infiniband/core/cm.c')
-rw-r--r--drivers/infiniband/core/cm.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 0685cb2a88c0..cad3c58e660c 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -825,6 +825,8 @@ struct ib_cm_id *ib_create_cm_id(struct ib_device *device,
cm_id_priv->id.context = context;
cm_id_priv->id.remote_cm_qpn = 1;
+ RB_CLEAR_NODE(&cm_id_priv->service_node);
+ RB_CLEAR_NODE(&cm_id_priv->sidr_id_node);
spin_lock_init(&cm_id_priv->lock);
init_completion(&cm_id_priv->comp);
INIT_LIST_HEAD(&cm_id_priv->work_list);
@@ -982,11 +984,13 @@ retest:
spin_lock_irq(&cm.lock);
if (--cm_id_priv->listen_sharecount > 0) {
/* The id is still shared. */
+ WARN_ON(refcount_read(&cm_id_priv->refcount) == 1);
cm_deref_id(cm_id_priv);
spin_unlock_irq(&cm.lock);
return;
}
rb_erase(&cm_id_priv->service_node, &cm.listen_service_table);
+ RB_CLEAR_NODE(&cm_id_priv->service_node);
spin_unlock_irq(&cm.lock);
break;
case IB_CM_SIDR_REQ_SENT:
@@ -997,11 +1001,6 @@ retest:
case IB_CM_SIDR_REQ_RCVD:
spin_unlock_irq(&cm_id_priv->lock);
cm_reject_sidr_req(cm_id_priv, IB_SIDR_REJECT);
- spin_lock_irq(&cm.lock);
- if (!RB_EMPTY_NODE(&cm_id_priv->sidr_id_node))
- rb_erase(&cm_id_priv->sidr_id_node,
- &cm.remote_sidr_table);
- spin_unlock_irq(&cm.lock);
break;
case IB_CM_REQ_SENT:
case IB_CM_MRA_REQ_RCVD:
@@ -1068,6 +1067,10 @@ retest:
if (!list_empty(&cm_id_priv->prim_list) &&
(!cm_id_priv->prim_send_port_not_ready))
list_del(&cm_id_priv->prim_list);
+ WARN_ON(cm_id_priv->listen_sharecount);
+ WARN_ON(!RB_EMPTY_NODE(&cm_id_priv->service_node));
+ if (!RB_EMPTY_NODE(&cm_id_priv->sidr_id_node))
+ rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table);
spin_unlock(&cm.lock);
spin_unlock_irq(&cm_id_priv->lock);