summaryrefslogtreecommitdiffstats
path: root/mm/vmscan.c
diff options
context:
space:
mode:
authorMel Gorman <mgorman@techsingularity.net>2016-09-01 19:14:55 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-09-01 20:52:01 -0400
commit6aa303defb7454a2520c4ddcdf6b081f62a15890 (patch)
treef29799a63374ed8b39114c8f55bc10f52b679737 /mm/vmscan.c
parente6173ba42bbdba05fd4f3021c0beda0506271507 (diff)
mm, vmscan: only allocate and reclaim from zones with pages managed by the buddy allocator
Firmware Assisted Dump (FA_DUMP) on ppc64 reserves substantial amounts of memory when booting a secondary kernel. Srikar Dronamraju reported that multiple nodes may have no memory managed by the buddy allocator but still return true for populated_zone(). Commit 1d82de618ddd ("mm, vmscan: make kswapd reclaim in terms of nodes") was reported to cause kswapd to spin at 100% CPU usage when fadump was enabled. The old code happened to deal with the situation of a populated node with zero free pages by co-incidence but the current code tries to reclaim populated zones without realising that is impossible. We cannot just convert populated_zone() as many existing users really need to check for present_pages. This patch introduces a managed_zone() helper and uses it in the few cases where it is critical that the check is made for managed pages -- zonelist construction and page reclaim. Link: http://lkml.kernel.org/r/20160831195104.GB8119@techsingularity.net Signed-off-by: Mel Gorman <mgorman@techsingularity.net> Reported-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com> Tested-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com> Acked-by: Michal Hocko <mhocko@suse.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/vmscan.c')
-rw-r--r--mm/vmscan.c22
1 files changed, 11 insertions, 11 deletions
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 374d95d04178..b1e12a1ea9cf 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1665,7 +1665,7 @@ static bool inactive_reclaimable_pages(struct lruvec *lruvec,
1665 1665
1666 for (zid = sc->reclaim_idx; zid >= 0; zid--) { 1666 for (zid = sc->reclaim_idx; zid >= 0; zid--) {
1667 zone = &pgdat->node_zones[zid]; 1667 zone = &pgdat->node_zones[zid];
1668 if (!populated_zone(zone)) 1668 if (!managed_zone(zone))
1669 continue; 1669 continue;
1670 1670
1671 if (zone_page_state_snapshot(zone, NR_ZONE_LRU_BASE + 1671 if (zone_page_state_snapshot(zone, NR_ZONE_LRU_BASE +
@@ -2036,7 +2036,7 @@ static bool inactive_list_is_low(struct lruvec *lruvec, bool file,
2036 struct zone *zone = &pgdat->node_zones[zid]; 2036 struct zone *zone = &pgdat->node_zones[zid];
2037 unsigned long inactive_zone, active_zone; 2037 unsigned long inactive_zone, active_zone;
2038 2038
2039 if (!populated_zone(zone)) 2039 if (!managed_zone(zone))
2040 continue; 2040 continue;
2041 2041
2042 inactive_zone = zone_page_state(zone, 2042 inactive_zone = zone_page_state(zone,
@@ -2171,7 +2171,7 @@ static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg,
2171 2171
2172 for (z = 0; z < MAX_NR_ZONES; z++) { 2172 for (z = 0; z < MAX_NR_ZONES; z++) {
2173 struct zone *zone = &pgdat->node_zones[z]; 2173 struct zone *zone = &pgdat->node_zones[z];
2174 if (!populated_zone(zone)) 2174 if (!managed_zone(zone))
2175 continue; 2175 continue;
2176 2176
2177 total_high_wmark += high_wmark_pages(zone); 2177 total_high_wmark += high_wmark_pages(zone);
@@ -2510,7 +2510,7 @@ static inline bool should_continue_reclaim(struct pglist_data *pgdat,
2510 /* If compaction would go ahead or the allocation would succeed, stop */ 2510 /* If compaction would go ahead or the allocation would succeed, stop */
2511 for (z = 0; z <= sc->reclaim_idx; z++) { 2511 for (z = 0; z <= sc->reclaim_idx; z++) {
2512 struct zone *zone = &pgdat->node_zones[z]; 2512 struct zone *zone = &pgdat->node_zones[z];
2513 if (!populated_zone(zone)) 2513 if (!managed_zone(zone))
2514 continue; 2514 continue;
2515 2515
2516 switch (compaction_suitable(zone, sc->order, 0, sc->reclaim_idx)) { 2516 switch (compaction_suitable(zone, sc->order, 0, sc->reclaim_idx)) {
@@ -2840,7 +2840,7 @@ static bool pfmemalloc_watermark_ok(pg_data_t *pgdat)
2840 2840
2841 for (i = 0; i <= ZONE_NORMAL; i++) { 2841 for (i = 0; i <= ZONE_NORMAL; i++) {
2842 zone = &pgdat->node_zones[i]; 2842 zone = &pgdat->node_zones[i];
2843 if (!populated_zone(zone) || 2843 if (!managed_zone(zone) ||
2844 pgdat_reclaimable_pages(pgdat) == 0) 2844 pgdat_reclaimable_pages(pgdat) == 0)
2845 continue; 2845 continue;
2846 2846
@@ -3141,7 +3141,7 @@ static bool prepare_kswapd_sleep(pg_data_t *pgdat, int order, int classzone_idx)
3141 for (i = 0; i <= classzone_idx; i++) { 3141 for (i = 0; i <= classzone_idx; i++) {
3142 struct zone *zone = pgdat->node_zones + i; 3142 struct zone *zone = pgdat->node_zones + i;
3143 3143
3144 if (!populated_zone(zone)) 3144 if (!managed_zone(zone))
3145 continue; 3145 continue;
3146 3146
3147 if (!zone_balanced(zone, order, classzone_idx)) 3147 if (!zone_balanced(zone, order, classzone_idx))
@@ -3169,7 +3169,7 @@ static bool kswapd_shrink_node(pg_data_t *pgdat,
3169 sc->nr_to_reclaim = 0; 3169 sc->nr_to_reclaim = 0;
3170 for (z = 0; z <= sc->reclaim_idx; z++) { 3170 for (z = 0; z <= sc->reclaim_idx; z++) {
3171 zone = pgdat->node_zones + z; 3171 zone = pgdat->node_zones + z;
3172 if (!populated_zone(zone)) 3172 if (!managed_zone(zone))
3173 continue; 3173 continue;
3174 3174
3175 sc->nr_to_reclaim += max(high_wmark_pages(zone), SWAP_CLUSTER_MAX); 3175 sc->nr_to_reclaim += max(high_wmark_pages(zone), SWAP_CLUSTER_MAX);
@@ -3242,7 +3242,7 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx)
3242 if (buffer_heads_over_limit) { 3242 if (buffer_heads_over_limit) {
3243 for (i = MAX_NR_ZONES - 1; i >= 0; i--) { 3243 for (i = MAX_NR_ZONES - 1; i >= 0; i--) {
3244 zone = pgdat->node_zones + i; 3244 zone = pgdat->node_zones + i;
3245 if (!populated_zone(zone)) 3245 if (!managed_zone(zone))
3246 continue; 3246 continue;
3247 3247
3248 sc.reclaim_idx = i; 3248 sc.reclaim_idx = i;
@@ -3262,7 +3262,7 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx)
3262 */ 3262 */
3263 for (i = classzone_idx; i >= 0; i--) { 3263 for (i = classzone_idx; i >= 0; i--) {
3264 zone = pgdat->node_zones + i; 3264 zone = pgdat->node_zones + i;
3265 if (!populated_zone(zone)) 3265 if (!managed_zone(zone))
3266 continue; 3266 continue;
3267 3267
3268 if (zone_balanced(zone, sc.order, classzone_idx)) 3268 if (zone_balanced(zone, sc.order, classzone_idx))
@@ -3508,7 +3508,7 @@ void wakeup_kswapd(struct zone *zone, int order, enum zone_type classzone_idx)
3508 pg_data_t *pgdat; 3508 pg_data_t *pgdat;
3509 int z; 3509 int z;
3510 3510
3511 if (!populated_zone(zone)) 3511 if (!managed_zone(zone))
3512 return; 3512 return;
3513 3513
3514 if (!cpuset_zone_allowed(zone, GFP_KERNEL | __GFP_HARDWALL)) 3514 if (!cpuset_zone_allowed(zone, GFP_KERNEL | __GFP_HARDWALL))
@@ -3522,7 +3522,7 @@ void wakeup_kswapd(struct zone *zone, int order, enum zone_type classzone_idx)
3522 /* Only wake kswapd if all zones are unbalanced */ 3522 /* Only wake kswapd if all zones are unbalanced */
3523 for (z = 0; z <= classzone_idx; z++) { 3523 for (z = 0; z <= classzone_idx; z++) {
3524 zone = pgdat->node_zones + z; 3524 zone = pgdat->node_zones + z;
3525 if (!populated_zone(zone)) 3525 if (!managed_zone(zone))
3526 continue; 3526 continue;
3527 3527
3528 if (zone_balanced(zone, order, classzone_idx)) 3528 if (zone_balanced(zone, order, classzone_idx))