From f6febf2dafaf453d887a7bc73820c1a88cda553b Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 12 Sep 2013 13:21:42 +0200 Subject: [PATCH] mm/shrinker: flag to always shrink a bit Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 1 + include/linux/shrinker.h | 14 ++++++++++++++ mm/vmscan.c | 4 ++++ 3 files changed, 19 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index d80f33d..7481d0a 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4582,6 +4582,7 @@ i915_gem_load(struct drm_device *dev) dev_priv->mm.inactive_shrinker.shrink = i915_gem_inactive_shrink; dev_priv->mm.inactive_shrinker.seeks = DEFAULT_SEEKS; + dev_priv->mm.inactive_shrinker.evicts_to_page_lru = true; register_shrinker(&dev_priv->mm.inactive_shrinker); } diff --git a/include/linux/shrinker.h b/include/linux/shrinker.h index ac6b8ee..361cc2d 100644 --- a/include/linux/shrinker.h +++ b/include/linux/shrinker.h @@ -32,6 +32,20 @@ struct shrinker { int seeks; /* seeks to recreate an obj */ long batch; /* reclaim batch size, 0 = default */ + /* + * Some shrinkers (especially gpu drivers using gem as backing storage) + * hold onto gobloads of pinned pagecache memory (from shmem nodes). + * When those caches get shrunk the memory only gets unpin and so is + * available to be evicted with the page launderer. + * + * The problem is that the core mm tries to balance eviction from the + * page lru with shrinking caches. So if there's nothing on the page lru + * to evict we'll never shrink the gpu driver caches and so will OOM + * despite tons of memory used by gpu buffer objects that could be + * swapped out. Setting this flag ensures forward progress. + */ + bool evicts_to_page_lru; + /* These are for internal use */ struct list_head list; atomic_long_t nr_in_batch; /* objs pending delete */ diff --git a/mm/vmscan.c b/mm/vmscan.c index 2cff0d4..d81f6e0 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -254,6 +254,10 @@ unsigned long shrink_slab(struct shrink_control *shrink, total_scan = max_pass; } + /* Always try to shrink a bit to make forward progress. */ + if (shrinker->evicts_to_page_lru) + total_scan = max_t(long, total_scan, batch_size); + /* * We need to avoid excessive windup on filesystem shrinkers * due to large numbers of GFP_NOFS allocations causing the -- 1.8.4.rc3