Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/gem: Make drm_gem_objects_lookup() self-cleaning on failure v6

drm_gem_objects_lookup() can allocate the output array and take
references on GEM objects before it fails.

If an error happens part-way through, callers previously had to clean up
partially created results themselves. This relied on subtle and
undocumented behavior and was easy to get wrong.

Make drm_gem_objects_lookup() clean up on failure. The function now
drops any references it already took, frees the array, and sets
*objs_out to NULL before returning an error.

On success, behavior is unchanged. Existing callers remain correct and
their error cleanup paths simply do nothing when *objs_out is NULL.

v2/v3: Move partial-lookup cleanup into objects_lookup(), perform
reference dropping outside the lock, and remove reliance on __GFP_ZERO
or implicit NULL handling. (Christian)

v4: Use goto-style error handling in objects_lookup(), drop partial
references outside the lock, and simplify drm_gem_objects_lookup()
cleanup by routing failures through err_free_handles as suggested.
(Christian)

v5: Rebase on drm-misc-next, drop the ret local variable. (Christian)

v6: Drop superfluous initialization of handles. (Christian/Tvrtko)

Cc: Alex Deucher <alexander.deucher@amd.com>
Suggested-by: Christian König <christian.koenig@amd.com>
Suggested-by: Tvrtko Ursulin <tursulin@ursulin.net>
Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Signed-off-by: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com>
Link: https://patch.msgid.link/20260206132141.1474191-1-srinivasan.shanmugam@amd.com

authored by

Srinivasan Shanmugam and committed by
Arunpravin Paneer Selvam
dbce4317 8ad0f7d2

+31 -14
+31 -14
drivers/gpu/drm/drm_gem.c
··· 783 783 static int objects_lookup(struct drm_file *filp, u32 *handle, int count, 784 784 struct drm_gem_object **objs) 785 785 { 786 - int i, ret = 0; 786 + int i; 787 787 struct drm_gem_object *obj; 788 788 789 789 spin_lock(&filp->table_lock); ··· 791 791 for (i = 0; i < count; i++) { 792 792 /* Check if we currently have a reference on the object */ 793 793 obj = idr_find(&filp->object_idr, handle[i]); 794 - if (!obj) { 795 - ret = -ENOENT; 796 - break; 797 - } 794 + if (!obj) 795 + goto err; 796 + 798 797 drm_gem_object_get(obj); 799 798 objs[i] = obj; 800 799 } 800 + 801 + spin_unlock(&filp->table_lock); 802 + return 0; 803 + 804 + err: 801 805 spin_unlock(&filp->table_lock); 802 806 803 - return ret; 807 + while (i--) 808 + drm_gem_object_put(objs[i]); 809 + 810 + return -ENOENT; 804 811 } 805 812 806 813 /** ··· 835 828 u32 *handles; 836 829 int ret; 837 830 831 + *objs_out = NULL; 832 + 838 833 if (!count) 839 834 return 0; 840 835 841 - objs = kvmalloc_array(count, sizeof(struct drm_gem_object *), 842 - GFP_KERNEL | __GFP_ZERO); 836 + objs = kvmalloc_array(count, sizeof(*objs), GFP_KERNEL); 843 837 if (!objs) 844 838 return -ENOMEM; 845 839 846 - *objs_out = objs; 847 - 848 840 handles = vmemdup_array_user(bo_handles, count, sizeof(u32)); 849 - if (IS_ERR(handles)) 850 - return PTR_ERR(handles); 841 + if (IS_ERR(handles)) { 842 + ret = PTR_ERR(handles); 843 + goto err_free_objs; 844 + } 851 845 852 846 ret = objects_lookup(filp, handles, count, objs); 853 - kvfree(handles); 854 - return ret; 847 + if (ret) 848 + goto err_free_handles; 855 849 850 + kvfree(handles); 851 + *objs_out = objs; 852 + return 0; 853 + 854 + err_free_handles: 855 + kvfree(handles); 856 + err_free_objs: 857 + kvfree(objs); 858 + return ret; 856 859 } 857 860 EXPORT_SYMBOL(drm_gem_objects_lookup); 858 861