If most processes reside in memory cgroups protected with memory.low,
there won't be a lot of pages in the root cgroup's lruvec so that the
lru scanned/eligible ratio can get high even on the initial scan
priority. In this case global slab caches will be evicted far too
aggressively. Tcache/tswap are especially affected - if the node is
undercommitted, they may occupy gigabytes of RAM which can be dropped in
an instant even on very low memory pressure.

To fix this, we forge scanned/eligible ratio passed to slab shrinkers if
the number of pages on the root lruvec is small.

Signed-off-by: Vladimir Davydov <[email protected]>
---
 mm/vmscan.c | 25 ++++++++++++++++++++++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/mm/vmscan.c b/mm/vmscan.c
index 0406c11287f5..a7cc964f0835 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -2388,10 +2388,29 @@ static void shrink_zone(struct zone *zone, struct 
scan_control *sc,
                 * Shrink the slab caches in the same proportion that
                 * the eligible LRU pages were scanned.
                 */
-               if (global_reclaim(sc) && is_classzone)
+               if (global_reclaim(sc) && is_classzone) {
+                       unsigned long scanned, eligible;
+
+                       scanned = sc->nr_scanned - nr_scanned;
+                       eligible = zone_lru_pages;
+
+                       /*
+                        * If most processes reside in memory cgroups protected
+                        * with memory.low there won't be a lot of user pages
+                        * in the root lruvec so that the lru scanned/eligible
+                        * ratio ratio can get high even on the default scan
+                        * priority. In order not to subject memcg unaware slab
+                        * caches to disproportionately high pressure, we forge
+                        * the ratio in this case.
+                        */
+                       if (eligible >> sc->priority == 0) {
+                               scanned = 1000;
+                               eligible = 1000 << sc->priority;
+                       }
+
                        shrink_slab(slab_gfp, zone_to_nid(zone), NULL,
-                                   sc->nr_scanned - nr_scanned,
-                                   zone_lru_pages);
+                                   scanned, eligible);
+               }
 
                if (reclaim_state) {
                        sc->nr_reclaimed += reclaim_state->reclaimed_slab;
-- 
2.1.4

_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to