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.