]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
ib/core: init shared-pd ref count to 1, and add cleanup
authorArun Kaimalettu <arun.kaimalettu@oracle.com>
Mon, 18 Jul 2011 12:21:34 +0000 (15:21 +0300)
committerMukesh Kacker <mukesh.kacker@oracle.com>
Fri, 11 Sep 2015 17:14:25 +0000 (10:14 -0700)
When shpd is created it is already referred to by parent 'pd',
so shpd->shared should be '1' initially (and not '0');
otherwise, the 'shpd' memory may get freed/reallocated
while it is still being referred to by one last pd.

Additionally, add shared-pd cleanup to ucontext cleanup flow.

Orabug: 21496696

Signed-off-by: Arun Kaimalettu <arun.kaimalettu@oracle.com>
Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il>
(Ported from UEK2/OFED 1.5.5)

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

index 2f5d5441f7673271fcf796f105002a12acf710f9..ccb9270f0557a4d9f7d8c19a5f33d1f7fb05a6fb 100644 (file)
@@ -663,6 +663,8 @@ ssize_t ib_uverbs_alloc_shpd(struct ib_uverbs_file *file,
        shpd->device = file->device->ib_dev;
        shpd->uobject = shuobj;
        shpd->share_key = cmd.share_key;
+       /* initialize shared count for this shpd */
+       atomic_set(&shpd->shared, 1);
 
        shuobj->object = shpd;
 
@@ -848,10 +850,9 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file,
 
        if (!ret && shpd) {
                down_write(&shuobj->mutex);
-               atomic_dec(&shpd->shared);
 
                /* if this shpd is no longer shared */
-               if (!atomic_read(&shpd->shared)) {
+               if (atomic_dec_and_test(&shpd->shared)) {
                        /* free the shpd info from device driver */
                        file->device->ib_dev->remove_shpd(file->device->ib_dev,
                                                          shpd, 0);
index 32c654abfc2f50835ce4bcce49c5c7e526ca2c3e..ca4e0cc234deae96af066f2a356c8f9d29fa0453 100644 (file)
@@ -137,6 +137,16 @@ static int (*uverbs_ex_cmd_table[])(struct ib_uverbs_file *file,
 static void ib_uverbs_add_one(struct ib_device *device);
 static void ib_uverbs_remove_one(struct ib_device *device);
 
+static void release_uobj(struct kref *kref)
+{
+       kfree(container_of(kref, struct ib_uobject, ref));
+}
+
+static void put_uobj(struct ib_uobject *uobj)
+{
+       kref_put(&uobj->ref, release_uobj);
+}
+
 static void ib_uverbs_release_dev(struct kref *ref)
 {
        struct ib_uverbs_device *dev =
@@ -304,9 +314,39 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
 
        list_for_each_entry_safe(uobj, tmp, &context->pd_list, list) {
                struct ib_pd *pd = uobj->object;
+               struct ib_uobject          *shuobj = NULL;
+               struct ib_shpd             *shpd = NULL;
 
                idr_remove_uobj(&ib_uverbs_pd_idr, uobj);
+
+               /* is pd shared ?*/
+               if (pd->shpd) {
+                       shpd = pd->shpd;
+                       shuobj = shpd->uobject;
+               }
+
                ib_dealloc_pd(pd);
+
+               if (shpd) {
+
+                       down_write(&shuobj->mutex);
+
+                       /* if this shpd is no longer shared */
+                       if (atomic_dec_and_test(&shpd->shared)) {
+                               /* free the shpd info from device driver */
+                               file->device->ib_dev->remove_shpd(
+                                         file->device->ib_dev, shpd, 0);
+                               shuobj->live = 0;
+                               up_write(&shuobj->mutex);
+                               idr_remove_uobj(&ib_uverbs_shpd_idr, shuobj);
+                               /*
+                                * there could some one waiting to
+                                * lock this shared object
+                                */
+                               put_uobj(shuobj);
+                       } else
+                               up_write(&shuobj->mutex);
+               }
                kfree(uobj);
        }