All of lore.kernel.org
 help / color / mirror / Atom feed
diff for duplicates of <20141128160637.GH6948@esperanza>

diff --git a/a/1.txt b/N1/1.txt
index 513e7a3..80b8cd1 100644
--- a/a/1.txt
+++ b/N1/1.txt
@@ -67,3 +67,115 @@ empty ZONE_NORMAL on x86_64.
 
 What about distributing the pressure proportionally to the number of
 present pages on the zone? Something like this:
+
+>From 5face0e29300950575bf9ccbd995828e2f183da1 Mon Sep 17 00:00:00 2001
+From: Vladimir Davydov <vdavydov@parallels.com>
+Date: Fri, 28 Nov 2014 17:58:43 +0300
+Subject: [PATCH] vmscan: fix slab vs page cache reclaim balance
+
+Though page cache reclaim is done per-zone, the finest granularity for
+slab cache reclaim is per node. To achieve proportional pressure being
+put on them, we therefore shrink slab caches only when scanning the
+class zone, which is the highest zone suitable for allocations. However,
+the class zone may be empty, e.g. ZONE_NORMAL/ZONE_HIGH, which are class
+zones for most allocations, are empty on x86_64 with < 4G of RAM. This
+will result in slab cache being scanned only by kswapd, which in turn
+may lead to a premature OOM kill.
+
+This patch attempts to fix this by calling shrink_node_slabs per each
+zone eligible while distributing the pressure between zones
+proportionally to the number of present pages.
+
+Signed-off-by: Vladimir Davydov <vdavydov@parallels.com>
+
+diff --git a/mm/vmscan.c b/mm/vmscan.c
+index 9130cf67bac1..dd80625a1be5 100644
+--- a/mm/vmscan.c
++++ b/mm/vmscan.c
+@@ -2298,8 +2298,7 @@ static inline bool should_continue_reclaim(struct zone *zone,
+ 	}
+ }
+ 
+-static bool shrink_zone(struct zone *zone, struct scan_control *sc,
+-			bool is_classzone)
++static bool shrink_zone(struct zone *zone, struct scan_control *sc)
+ {
+ 	unsigned long nr_reclaimed, nr_scanned;
+ 	bool reclaimable = false;
+@@ -2310,7 +2309,7 @@ static bool shrink_zone(struct zone *zone, struct scan_control *sc,
+ 			.zone = zone,
+ 			.priority = sc->priority,
+ 		};
+-		unsigned long zone_lru_pages = 0;
++		unsigned long nr_eligible = 0;
+ 		struct mem_cgroup *memcg;
+ 
+ 		nr_reclaimed = sc->nr_reclaimed;
+@@ -2319,6 +2318,7 @@ static bool shrink_zone(struct zone *zone, struct scan_control *sc,
+ 		memcg = mem_cgroup_iter(root, NULL, &reclaim);
+ 		do {
+ 			unsigned long lru_pages;
++			unsigned long long tmp;
+ 			struct lruvec *lruvec;
+ 			int swappiness;
+ 
+@@ -2326,7 +2326,17 @@ static bool shrink_zone(struct zone *zone, struct scan_control *sc,
+ 			swappiness = mem_cgroup_swappiness(memcg);
+ 
+ 			shrink_lruvec(lruvec, swappiness, sc, &lru_pages);
+-			zone_lru_pages += lru_pages;
++
++			/*
++			 * Scale lru_pages inversely proportionally to the zone
++			 * size in order to not over-reclaim slab caches, which
++			 * are zone unaware.
++			 */
++			tmp = lru_pages;
++			tmp *= zone->zone_pgdat->node_present_pages;
++			do_div(tmp, zone->present_pages);
++
++			nr_eligible += tmp;
+ 
+ 			/*
+ 			 * Direct reclaim and kswapd have to scan all memory
+@@ -2350,12 +2360,12 @@ static bool 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)) {
+ 			struct reclaim_state *reclaim_state;
+ 
+ 			shrink_node_slabs(sc->gfp_mask, zone_to_nid(zone),
+ 					  sc->nr_scanned - nr_scanned,
+-					  zone_lru_pages);
++					  nr_eligible);
+ 
+ 			reclaim_state = current->reclaim_state;
+ 			if (reclaim_state) {
+@@ -2503,7 +2513,7 @@ static bool shrink_zones(struct zonelist *zonelist, struct scan_control *sc)
+ 			/* need some check for avoid more shrink_zone() */
+ 		}
+ 
+-		if (shrink_zone(zone, sc, zone_idx(zone) == requested_highidx))
++		if (shrink_zone(zone, sc))
+ 			reclaimable = true;
+ 
+ 		if (global_reclaim(sc) &&
+@@ -3010,7 +3020,7 @@ static bool kswapd_shrink_zone(struct zone *zone,
+ 						balance_gap, classzone_idx))
+ 		return true;
+ 
+-	shrink_zone(zone, sc, zone_idx(zone) == classzone_idx);
++	shrink_zone(zone, sc);
+ 
+ 	/* Account for the number of pages attempted to reclaim */
+ 	*nr_attempted += sc->nr_to_reclaim;
+@@ -3656,7 +3666,7 @@ static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
+ 		 * priorities until we have enough memory freed.
+ 		 */
+ 		do {
+-			shrink_zone(zone, &sc, true);
++			shrink_zone(zone, &sc);
+ 		} while (sc.nr_reclaimed < nr_pages && --sc.priority >= 0);
+ 	}
diff --git a/a/content_digest b/N1/content_digest
index 81db902..5a72660 100644
--- a/a/content_digest
+++ b/N1/content_digest
@@ -5,8 +5,8 @@
  "To\0Johannes Weiner <hannes@cmpxchg.org>\0"
  "Cc\0Andrew Morton <akpm@linux-foundation.org>"
   Dave Chinner <david@fromorbit.com>
-  linux-mm@kvack.org
- " linux-kernel@vger.kernel.org\0"
+  <linux-mm@kvack.org>
+ " <linux-kernel@vger.kernel.org>\0"
  "\00:1\0"
  "b\0"
  "Hi Johannes,\n"
@@ -77,6 +77,118 @@
  "empty ZONE_NORMAL on x86_64.\n"
  "\n"
  "What about distributing the pressure proportionally to the number of\n"
- present pages on the zone? Something like this:
+ "present pages on the zone? Something like this:\n"
+ "\n"
+ ">From 5face0e29300950575bf9ccbd995828e2f183da1 Mon Sep 17 00:00:00 2001\n"
+ "From: Vladimir Davydov <vdavydov@parallels.com>\n"
+ "Date: Fri, 28 Nov 2014 17:58:43 +0300\n"
+ "Subject: [PATCH] vmscan: fix slab vs page cache reclaim balance\n"
+ "\n"
+ "Though page cache reclaim is done per-zone, the finest granularity for\n"
+ "slab cache reclaim is per node. To achieve proportional pressure being\n"
+ "put on them, we therefore shrink slab caches only when scanning the\n"
+ "class zone, which is the highest zone suitable for allocations. However,\n"
+ "the class zone may be empty, e.g. ZONE_NORMAL/ZONE_HIGH, which are class\n"
+ "zones for most allocations, are empty on x86_64 with < 4G of RAM. This\n"
+ "will result in slab cache being scanned only by kswapd, which in turn\n"
+ "may lead to a premature OOM kill.\n"
+ "\n"
+ "This patch attempts to fix this by calling shrink_node_slabs per each\n"
+ "zone eligible while distributing the pressure between zones\n"
+ "proportionally to the number of present pages.\n"
+ "\n"
+ "Signed-off-by: Vladimir Davydov <vdavydov@parallels.com>\n"
+ "\n"
+ "diff --git a/mm/vmscan.c b/mm/vmscan.c\n"
+ "index 9130cf67bac1..dd80625a1be5 100644\n"
+ "--- a/mm/vmscan.c\n"
+ "+++ b/mm/vmscan.c\n"
+ "@@ -2298,8 +2298,7 @@ static inline bool should_continue_reclaim(struct zone *zone,\n"
+ " \t}\n"
+ " }\n"
+ " \n"
+ "-static bool shrink_zone(struct zone *zone, struct scan_control *sc,\n"
+ "-\t\t\tbool is_classzone)\n"
+ "+static bool shrink_zone(struct zone *zone, struct scan_control *sc)\n"
+ " {\n"
+ " \tunsigned long nr_reclaimed, nr_scanned;\n"
+ " \tbool reclaimable = false;\n"
+ "@@ -2310,7 +2309,7 @@ static bool shrink_zone(struct zone *zone, struct scan_control *sc,\n"
+ " \t\t\t.zone = zone,\n"
+ " \t\t\t.priority = sc->priority,\n"
+ " \t\t};\n"
+ "-\t\tunsigned long zone_lru_pages = 0;\n"
+ "+\t\tunsigned long nr_eligible = 0;\n"
+ " \t\tstruct mem_cgroup *memcg;\n"
+ " \n"
+ " \t\tnr_reclaimed = sc->nr_reclaimed;\n"
+ "@@ -2319,6 +2318,7 @@ static bool shrink_zone(struct zone *zone, struct scan_control *sc,\n"
+ " \t\tmemcg = mem_cgroup_iter(root, NULL, &reclaim);\n"
+ " \t\tdo {\n"
+ " \t\t\tunsigned long lru_pages;\n"
+ "+\t\t\tunsigned long long tmp;\n"
+ " \t\t\tstruct lruvec *lruvec;\n"
+ " \t\t\tint swappiness;\n"
+ " \n"
+ "@@ -2326,7 +2326,17 @@ static bool shrink_zone(struct zone *zone, struct scan_control *sc,\n"
+ " \t\t\tswappiness = mem_cgroup_swappiness(memcg);\n"
+ " \n"
+ " \t\t\tshrink_lruvec(lruvec, swappiness, sc, &lru_pages);\n"
+ "-\t\t\tzone_lru_pages += lru_pages;\n"
+ "+\n"
+ "+\t\t\t/*\n"
+ "+\t\t\t * Scale lru_pages inversely proportionally to the zone\n"
+ "+\t\t\t * size in order to not over-reclaim slab caches, which\n"
+ "+\t\t\t * are zone unaware.\n"
+ "+\t\t\t */\n"
+ "+\t\t\ttmp = lru_pages;\n"
+ "+\t\t\ttmp *= zone->zone_pgdat->node_present_pages;\n"
+ "+\t\t\tdo_div(tmp, zone->present_pages);\n"
+ "+\n"
+ "+\t\t\tnr_eligible += tmp;\n"
+ " \n"
+ " \t\t\t/*\n"
+ " \t\t\t * Direct reclaim and kswapd have to scan all memory\n"
+ "@@ -2350,12 +2360,12 @@ static bool shrink_zone(struct zone *zone, struct scan_control *sc,\n"
+ " \t\t * Shrink the slab caches in the same proportion that\n"
+ " \t\t * the eligible LRU pages were scanned.\n"
+ " \t\t */\n"
+ "-\t\tif (global_reclaim(sc) && is_classzone) {\n"
+ "+\t\tif (global_reclaim(sc)) {\n"
+ " \t\t\tstruct reclaim_state *reclaim_state;\n"
+ " \n"
+ " \t\t\tshrink_node_slabs(sc->gfp_mask, zone_to_nid(zone),\n"
+ " \t\t\t\t\t  sc->nr_scanned - nr_scanned,\n"
+ "-\t\t\t\t\t  zone_lru_pages);\n"
+ "+\t\t\t\t\t  nr_eligible);\n"
+ " \n"
+ " \t\t\treclaim_state = current->reclaim_state;\n"
+ " \t\t\tif (reclaim_state) {\n"
+ "@@ -2503,7 +2513,7 @@ static bool shrink_zones(struct zonelist *zonelist, struct scan_control *sc)\n"
+ " \t\t\t/* need some check for avoid more shrink_zone() */\n"
+ " \t\t}\n"
+ " \n"
+ "-\t\tif (shrink_zone(zone, sc, zone_idx(zone) == requested_highidx))\n"
+ "+\t\tif (shrink_zone(zone, sc))\n"
+ " \t\t\treclaimable = true;\n"
+ " \n"
+ " \t\tif (global_reclaim(sc) &&\n"
+ "@@ -3010,7 +3020,7 @@ static bool kswapd_shrink_zone(struct zone *zone,\n"
+ " \t\t\t\t\t\tbalance_gap, classzone_idx))\n"
+ " \t\treturn true;\n"
+ " \n"
+ "-\tshrink_zone(zone, sc, zone_idx(zone) == classzone_idx);\n"
+ "+\tshrink_zone(zone, sc);\n"
+ " \n"
+ " \t/* Account for the number of pages attempted to reclaim */\n"
+ " \t*nr_attempted += sc->nr_to_reclaim;\n"
+ "@@ -3656,7 +3666,7 @@ static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)\n"
+ " \t\t * priorities until we have enough memory freed.\n"
+ " \t\t */\n"
+ " \t\tdo {\n"
+ "-\t\t\tshrink_zone(zone, &sc, true);\n"
+ "+\t\t\tshrink_zone(zone, &sc);\n"
+ " \t\t} while (sc.nr_reclaimed < nr_pages && --sc.priority >= 0);\n"
+ " \t}"
 
-3dbe08664271dc786f6572de842f2af44d5c1ff86c8afa6d5b23c8454ceda6b3
+f052192a284c3c567d6ce2bfba4574d1e910bb029279c2eb0be58b3705c141f2

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.