From: Saeed Mahameed Date: Wed, 4 Dec 2013 11:14:50 +0000 (+0200) Subject: rdma_cm: garbage-collection thread for rdma_destroy_id() X-Git-Tag: v4.1.12-92~293^2~1^2~58 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=4c12b497beb5f38679860206cc171d6ec7277d8a;p=users%2Fjedix%2Flinux-maple.git rdma_cm: garbage-collection thread for rdma_destroy_id() garbage-collection thread for rdma_destroy_id, so as not to paralyze ib_cm thread with wait_for_completion. Signed-off-by: Saeed Mahameed Extracted from following commit in Mellanox OFED-2.4 812c3972cf93e0d04f568ba353e87a1de7c9e006 (rdma_cm: race condition bug fixes) Signed-off-by: Ajaykumar Hotchandani (Ported from Mellanox OFED 2.4) Signed-off-by: Mukesh Kacker --- diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 031b377a1557a..b728f80d60b05 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -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);