/** * Removes the mapping from handle to filp for this object. */ static int drm_gem_handle_delete(struct drm_file *filp, int handle) { struct drm_device *dev; struct drm_gem_object *obj; /* This is gross. The idr system doesn't let us try a delete and * return an error code. It just spews if you fail at deleting. * So, we have to grab a lock around finding the object and then * doing the delete on it and dropping the refcount, or the user * could race us to double-decrement the refcount and cause a * use-after-free later. Given the frequency of our handle lookups, * we may want to use ida for number allocation and a hash table * for the pointers, anyway. */ spin_lock(&filp->table_lock); /* Check if we currently have a reference on the object */ obj = idr_find(&filp->object_idr, handle); if (obj == NULL) { spin_unlock(&filp->table_lock); return -EINVAL; } dev = obj->dev; /* Release reference and decrement refcount. */ idr_remove(&filp->object_idr, handle); spin_unlock(&filp->table_lock); mutex_lock(&dev->struct_mutex); drm_gem_object_handle_unreference(obj); mutex_unlock(&dev->struct_mutex); return 0; }
static int drm_gem_handle_delete(struct drm_file *filp, u32 handle) { struct drm_device *dev; struct drm_gem_object *obj; spin_lock(&filp->table_lock); obj = idr_find(&filp->object_idr, handle); if (obj == NULL) { spin_unlock(&filp->table_lock); return -EINVAL; } dev = obj->dev; idr_remove(&filp->object_idr, handle); spin_unlock(&filp->table_lock); mutex_lock(&dev->struct_mutex); drm_gem_object_handle_unreference(obj); mutex_unlock(&dev->struct_mutex); return 0; }
int radeon_gem_create_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { struct radeon_device *rdev = dev->dev_private; struct drm_radeon_gem_create *args = data; struct drm_gem_object *gobj; uint32_t handle; int r; args->size = roundup(args->size, PAGE_SIZE); r = radeon_gem_object_create(rdev, args->size, args->alignment, args->initial_domain, false, false, true, &gobj); if (r) { return r; } r = drm_gem_handle_create(filp, gobj, &handle); if (r) { mutex_lock(&dev->struct_mutex); drm_gem_object_unreference(gobj); mutex_unlock(&dev->struct_mutex); return r; } mutex_lock(&dev->struct_mutex); drm_gem_object_handle_unreference(gobj); mutex_unlock(&dev->struct_mutex); args->handle = handle; return 0; }
/** * Called at device close to release the file's * handle references on objects. */ static int drm_gem_object_release_handle(int id, void *ptr, void *data) { struct drm_gem_object *obj = ptr; drm_gem_object_handle_unreference(obj); return 0; }
static int drm_gem_object_release_handle(uint32_t name, void *ptr, void *arg) { struct drm_gem_object *obj; obj = ptr; drm_gem_object_handle_unreference(obj); return (0); }