summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2009-02-11 14:26:28 +0000
committerDave Airlie <airlied@redhat.com>2009-02-20 12:21:10 +1000
commit8d59bae5d9aae10ab230561519bfb97962509bcb (patch)
tree0be3a5e9cbb512e6ec933a8e74f59958c7ee8018
parenta35f2e2b83a789e189a501ebd722bc9a1310eb05 (diff)
downloadop-kernel-dev-8d59bae5d9aae10ab230561519bfb97962509bcb.zip
op-kernel-dev-8d59bae5d9aae10ab230561519bfb97962509bcb.tar.gz
drm: Do not leak a new reference for flink() on an existing name
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>
-rw-r--r--drivers/gpu/drm/drm_gem.c33
1 files changed, 16 insertions, 17 deletions
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index e5a8ebf..5dad6b9 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -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
OpenPOWER on IntegriCloud