]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
rdma_cm: garbage-collection thread for rdma_destroy_id()
authorSaeed Mahameed <saeedm@mellanox.com>
Wed, 4 Dec 2013 11:14:50 +0000 (13:14 +0200)
committerMukesh Kacker <mukesh.kacker@oracle.com>
Tue, 7 Jul 2015 21:45:15 +0000 (14:45 -0700)
garbage-collection thread for rdma_destroy_id,
so as not to paralyze ib_cm thread with wait_for_completion.

Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Extracted from following commit in Mellanox OFED-2.4
812c3972cf93e0d04f568ba353e87a1de7c9e006
(rdma_cm: race condition bug fixes)

Signed-off-by: Ajaykumar Hotchandani <ajaykumar.hotchandani@oracle.com>
(Ported from Mellanox OFED 2.4)

Signed-off-by: Mukesh Kacker <mukesh.kacker@oracle.com>
drivers/infiniband/core/cma.c

index 031b377a1557aebf7fe7a4dd9557f908b9831c9b..b728f80d60b05f29e43f1098bd6383ba315f4168 100644 (file)
@@ -84,6 +84,7 @@ static LIST_HEAD(dev_list);
 static LIST_HEAD(listen_any_list);
 static DEFINE_MUTEX(lock);
 static struct workqueue_struct *cma_wq;
+static struct workqueue_struct *cma_free_wq;
 static DEFINE_IDR(tcp_ps);
 static DEFINE_IDR(udp_ps);
 static DEFINE_IDR(ipoib_ps);
@@ -131,6 +132,7 @@ struct rdma_id_private {
        struct completion       comp;
        atomic_t                refcount;
        struct mutex            handler_mutex;
+       struct work_struct      work;  /* garbage coll */
 
        int                     backlog;
        int                     timeout_ms;
@@ -1040,6 +1042,19 @@ static void cma_leave_mc_groups(struct rdma_id_private *id_priv)
                }
        }
 }
+static void __rdma_free(struct work_struct *work)
+{
+       struct rdma_id_private *id_priv;
+       id_priv = container_of(work, struct rdma_id_private, work);
+
+       wait_for_completion(&id_priv->comp);
+
+       if (id_priv->internal_id)
+               cma_deref_id(id_priv->id.context);
+
+       kfree(id_priv->id.route.path_rec);
+       kfree(id_priv);
+}
 
 void rdma_destroy_id(struct rdma_cm_id *id)
 {
@@ -1076,13 +1091,8 @@ void rdma_destroy_id(struct rdma_cm_id *id)
 
        cma_release_port(id_priv);
        cma_deref_id(id_priv);
-       wait_for_completion(&id_priv->comp);
-
-       if (id_priv->internal_id)
-               cma_deref_id(id_priv->id.context);
-
-       kfree(id_priv->id.route.path_rec);
-       kfree(id_priv);
+       INIT_WORK(&id_priv->work, __rdma_free);
+       queue_work(cma_free_wq, &id_priv->work);
 }
 EXPORT_SYMBOL(rdma_destroy_id);
 
@@ -3682,12 +3692,16 @@ static const struct ibnl_client_cbs cma_cb_table[] = {
 
 static int __init cma_init(void)
 {
-       int ret;
+       int ret = -ENOMEM;
 
        cma_wq = create_singlethread_workqueue("rdma_cm");
        if (!cma_wq)
                return -ENOMEM;
 
+       cma_free_wq = create_singlethread_workqueue("rdma_cm_fr");
+       if (!cma_free_wq)
+               goto err1;
+
        ib_sa_register_client(&sa_client);
        rdma_addr_register_client(&addr_client);
        register_netdevice_notifier(&cma_nb);
@@ -3705,6 +3719,9 @@ err:
        unregister_netdevice_notifier(&cma_nb);
        rdma_addr_unregister_client(&addr_client);
        ib_sa_unregister_client(&sa_client);
+
+       destroy_workqueue(cma_free_wq);
+err1:
        destroy_workqueue(cma_wq);
        return ret;
 }
@@ -3716,6 +3733,8 @@ static void __exit cma_cleanup(void)
        unregister_netdevice_notifier(&cma_nb);
        rdma_addr_unregister_client(&addr_client);
        ib_sa_unregister_client(&sa_client);
+       flush_workqueue(cma_free_wq);
+       destroy_workqueue(cma_free_wq);
        destroy_workqueue(cma_wq);
        idr_destroy(&tcp_ps);
        idr_destroy(&udp_ps);