diff options
| -rw-r--r-- | drivers/gpu/drm/drm_gem.c | 43 |
1 files changed, 30 insertions, 13 deletions
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 7ff6b7bbeb73..c4a3de3b920e 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -783,7 +783,7 @@ EXPORT_SYMBOL(drm_gem_put_pages); static int objects_lookup(struct drm_file *filp, u32 *handle, int count, struct drm_gem_object **objs) { - int i, ret = 0; + int i; struct drm_gem_object *obj; spin_lock(&filp->table_lock); @@ -791,16 +791,23 @@ static int objects_lookup(struct drm_file *filp, u32 *handle, int count, for (i = 0; i < count; i++) { /* Check if we currently have a reference on the object */ obj = idr_find(&filp->object_idr, handle[i]); - if (!obj) { - ret = -ENOENT; - break; - } + if (!obj) + goto err; + drm_gem_object_get(obj); objs[i] = obj; } + spin_unlock(&filp->table_lock); + return 0; - return ret; +err: + spin_unlock(&filp->table_lock); + + while (i--) + drm_gem_object_put(objs[i]); + + return -ENOENT; } /** @@ -828,24 +835,34 @@ int drm_gem_objects_lookup(struct drm_file *filp, void __user *bo_handles, u32 *handles; int ret; + *objs_out = NULL; + if (!count) return 0; - objs = kvmalloc_array(count, sizeof(struct drm_gem_object *), - GFP_KERNEL | __GFP_ZERO); + objs = kvmalloc_array(count, sizeof(*objs), GFP_KERNEL); if (!objs) return -ENOMEM; - *objs_out = objs; - handles = vmemdup_array_user(bo_handles, count, sizeof(u32)); - if (IS_ERR(handles)) - return PTR_ERR(handles); + if (IS_ERR(handles)) { + ret = PTR_ERR(handles); + goto err_free_objs; + } ret = objects_lookup(filp, handles, count, objs); + if (ret) + goto err_free_handles; + kvfree(handles); - return ret; + *objs_out = objs; + return 0; +err_free_handles: + kvfree(handles); +err_free_objs: + kvfree(objs); + return ret; } EXPORT_SYMBOL(drm_gem_objects_lookup); |
