OSDN Git Service

drm/panfrost: Fix a race in panfrost_ioctl_madvise()
authorBoris Brezillon <boris.brezillon@collabora.com>
Fri, 29 Nov 2019 13:59:02 +0000 (14:59 +0100)
committerRob Herring <robh@kernel.org>
Fri, 6 Dec 2019 17:05:52 +0000 (11:05 -0600)
If 2 threads change the MADVISE property of the same BO in parallel we
might end up with an shmem->madv value that's inconsistent with the
presence of the BO in the shrinker list.

The easiest solution to fix that is to protect the
drm_gem_shmem_madvise() call with the shrinker lock.

Fixes: 013b65101315 ("drm/panfrost: Add madvise and shrinker support")
Cc: <stable@vger.kernel.org>
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Steven Price <steven.price@arm.com>
Acked-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Signed-off-by: Rob Herring <robh@kernel.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20191129135908.2439529-3-boris.brezillon@collabora.com
drivers/gpu/drm/panfrost/panfrost_drv.c

index 9d08613..8b8d654 100644 (file)
@@ -347,20 +347,19 @@ static int panfrost_ioctl_madvise(struct drm_device *dev, void *data,
                return -ENOENT;
        }
 
+       mutex_lock(&pfdev->shrinker_lock);
        args->retained = drm_gem_shmem_madvise(gem_obj, args->madv);
 
        if (args->retained) {
                struct panfrost_gem_object *bo = to_panfrost_bo(gem_obj);
 
-               mutex_lock(&pfdev->shrinker_lock);
-
                if (args->madv == PANFROST_MADV_DONTNEED)
-                       list_add_tail(&bo->base.madv_list, &pfdev->shrinker_list);
+                       list_add_tail(&bo->base.madv_list,
+                                     &pfdev->shrinker_list);
                else if (args->madv == PANFROST_MADV_WILLNEED)
                        list_del_init(&bo->base.madv_list);
-
-               mutex_unlock(&pfdev->shrinker_lock);
        }
+       mutex_unlock(&pfdev->shrinker_lock);
 
        drm_gem_object_put_unlocked(gem_obj);
        return 0;