]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
rds shouldn't release fmr when ib_device was already released.
authorZheng Li <zheng.x.li@oracle.com>
Tue, 4 Jun 2013 06:35:37 +0000 (14:35 +0800)
committerMukesh Kacker <mukesh.kacker@oracle.com>
Wed, 8 Jul 2015 20:37:58 +0000 (13:37 -0700)
Orabug: 16605377

when rds_ib_remove_one return, driver's mlx4_ib_removeone
function destroy ib_device, so we must clear rds_ibdev->dev
to NULL, or will cause crash when rds connection be released,
at the moment rds_ib_dev_free through ib_device
.i.e rds_ibdev->dev to release mr and fmr, reusing the
released ib_device will cause crash.

Signed-off-by: zheng.x.li@oracle.com
Signed-off-by: bang.nguyen@oracle.com
net/rds/ib.c

index ddeac1452c0acb5450d552c023df60996c1313fd..4eb29061ccac5c6106141e01ecd1511379c0c239 100644 (file)
@@ -153,14 +153,16 @@ static void rds_ib_dev_free(struct work_struct *work)
        struct rds_ib_device *rds_ibdev = container_of(work,
                                        struct rds_ib_device, free_work);
 
-       if (rds_ibdev->mr_8k_pool)
-               rds_ib_destroy_mr_pool(rds_ibdev->mr_8k_pool);
-       if (rds_ibdev->mr_1m_pool)
-               rds_ib_destroy_mr_pool(rds_ibdev->mr_1m_pool);
-       if (rds_ibdev->mr)
-               ib_dereg_mr(rds_ibdev->mr);
-       if (rds_ibdev->pd)
-               ib_dealloc_pd(rds_ibdev->pd);
+       if (rds_ibdev->dev) {
+               if (rds_ibdev->mr_8k_pool)
+                       rds_ib_destroy_mr_pool(rds_ibdev->mr_8k_pool);
+               if (rds_ibdev->mr_1m_pool)
+                       rds_ib_destroy_mr_pool(rds_ibdev->mr_1m_pool);
+               if (rds_ibdev->mr)
+                       ib_dereg_mr(rds_ibdev->mr);
+               if (rds_ibdev->pd)
+                       ib_dealloc_pd(rds_ibdev->pd);
+       }
        kfree(rds_ibdev->srq);
 
        list_for_each_entry_safe(i_ipaddr, i_next, &rds_ibdev->ipaddr_list, list) {
@@ -171,10 +173,13 @@ static void rds_ib_dev_free(struct work_struct *work)
        if (rds_ibdev->vector_load)
                kfree(rds_ibdev->vector_load);
 
-       WARN_ON(!waitqueue_active(&rds_ibdev->wait));
+       if (rds_ibdev->dev) {
+               WARN_ON(!waitqueue_active(&rds_ibdev->wait));
 
-       rds_ibdev->done = 1;
-       wake_up(&rds_ibdev->wait);
+               rds_ibdev->done = 1;
+               wake_up(&rds_ibdev->wait);
+       } else
+               kfree(rds_ibdev);
 }
 
 void rds_ib_dev_put(struct rds_ib_device *rds_ibdev)
@@ -248,12 +253,20 @@ void rds_ib_remove_one(struct ib_device *device)
        rds_ib_dev_put(rds_ibdev);
        rds_ib_dev_put(rds_ibdev);
 
-       if (!wait_event_timeout(rds_ibdev->wait, rds_ibdev->done, 30*HZ))
+       if (!wait_event_timeout(rds_ibdev->wait, rds_ibdev->done, 30*HZ)) {
                printk(KERN_WARNING "RDS/IB: device cleanup timed out after "
                        " 30 secs (refcount=%d)\n",
                         atomic_read(&rds_ibdev->refcount));
-
-       kfree(rds_ibdev);
+               /* when rds_ib_remove_one return, driver's mlx4_ib_removeone
+                * function destroy ib_device, so we must clear rds_ibdev->dev
+                * to NULL, or will cause crash when rds connection be released,
+                * at the moment rds_ib_dev_free through ib_device
+                * .i.e rds_ibdev->dev to release mr and fmr, reusing the
+                * released ib_device will cause crash.
+                */
+               rds_ibdev->dev = NULL;
+       } else
+               kfree(rds_ibdev);
 }
 
 struct ib_client rds_ib_client = {