{
struct drm_gem_mm *mm;
- spin_lock_init(&dev->object_name_lock);
+ mutex_init(&dev->object_name_lock);
idr_init(&dev->object_name_idr);
mm = kzalloc(sizeof(struct drm_gem_mm), GFP_KERNEL);
obj->filp = NULL;
kref_init(&obj->refcount);
- atomic_set(&obj->handle_count, 0);
+ obj->handle_count = 0;
obj->size = size;
}
EXPORT_SYMBOL(drm_gem_private_object_init);
struct drm_device *dev = obj->dev;
/* Remove any name for this object */
- 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
* that now.
* This cannot be the last reference, since the handle holds one too.
*/
kref_put(&obj->refcount, drm_gem_object_ref_bug);
- } else
- spin_unlock(&dev->object_name_lock);
-
+ }
}
-void
+static void
drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj)
{
- if (obj == NULL)
- return;
-
- if (atomic_read(&obj->handle_count) == 0)
+ if (WARN_ON(obj->handle_count == 0))
return;
/*
* checked for a name
*/
- if (atomic_dec_and_test(&obj->handle_count))
+ mutex_lock(&obj->dev->object_name_lock);
+ if (--obj->handle_count == 0)
drm_gem_object_handle_free(obj);
+ mutex_unlock(&obj->dev->object_name_lock);
+
drm_gem_object_unreference_unlocked(obj);
}
* Get the user-visible handle using idr. Preload and perform
* allocation under our spinlock.
*/
+ mutex_lock(&dev->object_name_lock);
idr_preload(GFP_KERNEL);
spin_lock(&file_priv->table_lock);
ret = idr_alloc(&file_priv->object_idr, obj, 1, 0, GFP_NOWAIT);
-
+ drm_gem_object_reference(obj);
+ obj->handle_count++;
spin_unlock(&file_priv->table_lock);
idr_preload_end();
- if (ret < 0)
+ mutex_unlock(&dev->object_name_lock);
+ if (ret < 0) {
+ drm_gem_object_handle_unreference_unlocked(obj);
return ret;
+ }
*handlep = ret;
- drm_gem_object_handle_reference(obj);
if (dev->driver->gem_open_object) {
ret = dev->driver->gem_open_object(obj, file_priv);
if (obj == NULL)
return -ENOENT;
+ mutex_lock(&dev->object_name_lock);
idr_preload(GFP_KERNEL);
- spin_lock(&dev->object_name_lock);
+ /* prevent races with concurrent gem_close. */
+ if (obj->handle_count == 0) {
+ ret = -ENOENT;
+ goto err;
+ }
+
if (!obj->name) {
ret = idr_alloc(&dev->object_name_idr, obj, 1, 0, GFP_NOWAIT);
if (ret < 0)
ret = 0;
err:
- spin_unlock(&dev->object_name_lock);
idr_preload_end();
+ mutex_unlock(&dev->object_name_lock);
drm_gem_object_unreference_unlocked(obj);
DRM_DEBUG("%s:hdl[%d]obj[0x%x]name[%d]\n",
if (!(dev->driver->driver_features & DRIVER_GEM))
return -ENODEV;
- spin_lock(&dev->object_name_lock);
+ mutex_lock(&dev->object_name_lock);
obj = idr_find(&dev->object_name_idr, (int) args->name);
if (obj)
drm_gem_object_reference(obj);
- spin_unlock(&dev->object_name_lock);
+ mutex_unlock(&dev->object_name_lock);
if (!obj)
return -ENOENT;