drm: Do not leak a new reference for flink() on an existing name
authorChris Wilson <chris@chris-wilson.co.uk>
Wed, 11 Feb 2009 14:26:28 +0000 (14:26 +0000)
committerDave Airlie <airlied@redhat.com>
Fri, 20 Feb 2009 02:21:10 +0000 (12:21 +1000)
The name table should only hold a single reference, so avoid leaking
additional references for secondary calls to flink().

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@linux.ie>
drivers/gpu/drm/drm_gem.c

index e5a8ebf..5dad6b9 100644 (file)
@@ -301,27 +301,25 @@ again:
        }
 
        spin_lock(&dev->object_name_lock);
-       if (obj->name) {
-               args->name = obj->name;
+       if (!obj->name) {
+               ret = idr_get_new_above(&dev->object_name_idr, obj, 1,
+                                       &obj->name);
+               args->name = (uint64_t) obj->name;
                spin_unlock(&dev->object_name_lock);
-               return 0;
-       }
-       ret = idr_get_new_above(&dev->object_name_idr, obj, 1,
-                                &obj->name);
-       spin_unlock(&dev->object_name_lock);
-       if (ret == -EAGAIN)
-               goto again;
 
-       if (ret != 0)
-               goto err;
+               if (ret == -EAGAIN)
+                       goto again;
 
-       /*
-        * Leave the reference from the lookup around as the
-        * name table now holds one
-        */
-       args->name = (uint64_t) obj->name;
+               if (ret != 0)
+                       goto err;
 
-       return 0;
+               /* Allocate a reference for the name table.  */
+               drm_gem_object_reference(obj);
+       } else {
+               args->name = (uint64_t) obj->name;
+               spin_unlock(&dev->object_name_lock);
+               ret = 0;
+       }
 
 err:
        mutex_lock(&dev->struct_mutex);
@@ -452,6 +450,7 @@ drm_gem_object_handle_free(struct kref *kref)
        spin_lock(&dev->object_name_lock);
        if (obj->name) {
                idr_remove(&dev->object_name_idr, obj->name);
+               obj->name = 0;
                spin_unlock(&dev->object_name_lock);
                /*
                 * The object name held a reference to this object, drop