[PATCH 3/7] drm/syncobj: Avoid one temporary allocation in drm_syncobj_array_find
Tvrtko Ursulin
tvrtko.ursulin at igalia.com
Tue Mar 25 09:26:36 UTC 2025
On 24/03/2025 22:29, Maíra Canal wrote:
> Hi Tvrtko,
>
> On 18/03/25 12:54, Tvrtko Ursulin wrote:
>> Drm_syncobj_array_find() helper is used from many userspace ioctl entry
>> points with the task of looking up userspace handles to internal objects.
>>
>> We can easily avoid one temporary allocation by making it read the
>> handles
>> as it is looking them up.
>>
>> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin at igalia.com>
>> ---
>> drivers/gpu/drm/drm_syncobj.c | 44 +++++++++++++++++------------------
>> 1 file changed, 21 insertions(+), 23 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/
>> drm_syncobj.c
>> index fd5ba6c89666..cdda2df06bec 100644
>> --- a/drivers/gpu/drm/drm_syncobj.c
>> +++ b/drivers/gpu/drm/drm_syncobj.c
>> @@ -1213,48 +1213,46 @@ signed long drm_timeout_abs_to_jiffies(int64_t
>> timeout_nsec)
>> EXPORT_SYMBOL(drm_timeout_abs_to_jiffies);
>> static int drm_syncobj_array_find(struct drm_file *file_private,
>> - void __user *user_handles,
>> - uint32_t count_handles,
>> + u32 __user *handles,
>> + uint32_t count,
>> struct drm_syncobj ***syncobjs_out)
>> {
>> - uint32_t i, *handles;
>> struct drm_syncobj **syncobjs;
>> + uint32_t i;
>> int ret;
>> - handles = kmalloc_array(count_handles, sizeof(*handles),
>> GFP_KERNEL);
>> - if (handles == NULL)
>> + if (!access_ok(handles, count * sizeof(*handles)))
>> + return -EFAULT;
>> +
>> + syncobjs = kmalloc_array(count, sizeof(*syncobjs), GFP_KERNEL);
>> + if (!syncobjs)
>> return -ENOMEM;
>> - if (copy_from_user(handles, user_handles,
>> - sizeof(uint32_t) * count_handles)) {
>> - ret = -EFAULT;
>> - goto err_free_handles;
>> - }
>> + for (i = 0; i < count; i++) {
>> + u64 handle;
>
> I believe this is a u32.
Well spotted.
>> - syncobjs = kmalloc_array(count_handles, sizeof(*syncobjs),
>> GFP_KERNEL);
>> - if (syncobjs == NULL) {
>> - ret = -ENOMEM;
>> - goto err_free_handles;
>> - }
>> -
>> - for (i = 0; i < count_handles; i++) {
>> - syncobjs[i] = drm_syncobj_find(file_private, handles[i]);
>> + if (__get_user(handle, handles++)) {
>> + ret = -EFAULT;
>> + syncobjs[i] = NULL;
>
> Do we need to assign syncobjs[i] to NULL? Can we just go to
> err_put_syncobjs?
>
>> + goto err_put_syncobjs;
>> + }
>> + syncobjs[i] = drm_syncobj_find(file_private, handle);
>> if (!syncobjs[i]) {
>> ret = -ENOENT;
>> goto err_put_syncobjs;
>> }
>> }
>> - kfree(handles);
>> *syncobjs_out = syncobjs;
>> return 0;
>> err_put_syncobjs:
>> - while (i-- > 0)
>> - drm_syncobj_put(syncobjs[i]);
>> + while (i > 0) {
>> + if (syncobjs[i])
>
> I'm not sure if I understand which scenario this would be needed. For
> the first syncobj that we don't find, we go to err_free_handles and
> AFAIU all previous syncobjs exist, so there wouldn't be a need to check
> if the syncobj != NULL.
Well spotted again. I don't remember why I thought I needed to change
this since it looks the old unwind works fine with added __get_user
failure path.
Regards,
Tvrtko
>> + drm_syncobj_put(syncobjs[i]);
>> + i--;
>> + }
>> kfree(syncobjs);
>> -err_free_handles:
>> - kfree(handles);
>> return ret;
>> }
>
More information about the dri-devel
mailing list