drm/msm/gem: Prevent blocking within shrinker loop
authorjsg <jsg@openbsd.org>
Tue, 28 Mar 2023 03:55:56 +0000 (03:55 +0000)
committerjsg <jsg@openbsd.org>
Tue, 28 Mar 2023 03:55:56 +0000 (03:55 +0000)
From Dmitry Osipenko
96a5aee27439e56fca69628c3f87a042e7026b3e in linux-6.1.y/6.1.21
9630b585b607bd26f505d34620b14d75b9a5af7d in mainline linux

sys/dev/pci/drm/drm_gem.c
sys/dev/pci/drm/include/drm/drm_gem.h

index d888467..b91420b 100644 (file)
@@ -1660,10 +1660,13 @@ EXPORT_SYMBOL(drm_gem_lru_move_tail);
  *
  * @lru: The LRU to scan
  * @nr_to_scan: The number of pages to try to reclaim
+ * @remaining: The number of pages left to reclaim, should be initialized by caller
  * @shrink: Callback to try to shrink/reclaim the object.
  */
 unsigned long
-drm_gem_lru_scan(struct drm_gem_lru *lru, unsigned nr_to_scan,
+drm_gem_lru_scan(struct drm_gem_lru *lru,
+                unsigned int nr_to_scan,
+                unsigned long *remaining,
                 bool (*shrink)(struct drm_gem_object *obj))
 {
        struct drm_gem_lru still_in_lru;
@@ -1702,8 +1705,10 @@ drm_gem_lru_scan(struct drm_gem_lru *lru, unsigned nr_to_scan,
                 * hit shrinker in response to trying to get backing pages
                 * for this obj (ie. while it's lock is already held)
                 */
-               if (!dma_resv_trylock(obj->resv))
+               if (!dma_resv_trylock(obj->resv)) {
+                       *remaining += obj->size >> PAGE_SHIFT;
                        goto tail;
+               }
 
                if (shrink(obj)) {
                        freed += obj->size >> PAGE_SHIFT;
index cd87867..4b4001f 100644 (file)
@@ -495,7 +495,9 @@ int drm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev,
 void drm_gem_lru_init(struct drm_gem_lru *lru, struct rwlock *lock);
 void drm_gem_lru_remove(struct drm_gem_object *obj);
 void drm_gem_lru_move_tail(struct drm_gem_lru *lru, struct drm_gem_object *obj);
-unsigned long drm_gem_lru_scan(struct drm_gem_lru *lru, unsigned nr_to_scan,
+unsigned long drm_gem_lru_scan(struct drm_gem_lru *lru,
+                              unsigned int nr_to_scan,
+                              unsigned long *remaining,
                               bool (*shrink)(struct drm_gem_object *obj));
 
 void drm_ref(struct uvm_object *);