From 03e6490b12cef507001f7afb03d5da63e2b2dc88 Mon Sep 17 00:00:00 2001 From: Vinayak Menon Date: Sat, 17 Jan 2015 21:51:48 +0530 Subject: [PATCH] mm: compaction: fix the page state calculation in too_many_isolated Commit "mm: vmscan: fix the page state calculation in too_many_isolated" fixed an issue where a number of tasks were blocked in reclaim path for seconds, because of vmstat_diff not being synced in time. A similar problem can happen in isolate_migratepages_block, where similar calculation is performed. This patch fixes that. Change-Id: Ie74f108ef770da688017b515fe37faea6f384589 Signed-off-by: Vinayak Menon --- mm/compaction.c | 42 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/mm/compaction.c b/mm/compaction.c index 70e6bec46dc2..f002a7fe7ef8 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -635,20 +635,52 @@ isolate_freepages_range(struct compact_control *cc, } /* Similar to reclaim, but different enough that they don't share logic */ -static bool too_many_isolated(struct zone *zone) +static bool __too_many_isolated(struct zone *zone, int safe) { unsigned long active, inactive, isolated; - inactive = node_page_state(zone->zone_pgdat, NR_INACTIVE_FILE) + + if (safe) { + inactive = node_page_state_snapshot(zone->zone_pgdat, + NR_INACTIVE_FILE) + + node_page_state_snapshot(zone->zone_pgdat, + NR_INACTIVE_ANON); + active = node_page_state_snapshot(zone->zone_pgdat, + NR_ACTIVE_FILE) + + node_page_state_snapshot(zone->zone_pgdat, + NR_ACTIVE_ANON); + isolated = node_page_state_snapshot(zone->zone_pgdat, + NR_ISOLATED_FILE) + + node_page_state_snapshot(zone->zone_pgdat, + NR_ISOLATED_ANON); + } else { + inactive = node_page_state(zone->zone_pgdat, NR_INACTIVE_FILE) + node_page_state(zone->zone_pgdat, NR_INACTIVE_ANON); - active = node_page_state(zone->zone_pgdat, NR_ACTIVE_FILE) + + active = node_page_state(zone->zone_pgdat, NR_ACTIVE_FILE) + node_page_state(zone->zone_pgdat, NR_ACTIVE_ANON); - isolated = node_page_state(zone->zone_pgdat, NR_ISOLATED_FILE) + + isolated = node_page_state(zone->zone_pgdat, NR_ISOLATED_FILE) + node_page_state(zone->zone_pgdat, NR_ISOLATED_ANON); + } return isolated > (inactive + active) / 2; } +/* Similar to reclaim, but different enough that they don't share logic */ +static bool too_many_isolated(struct compact_control *cc) +{ + /* + * __too_many_isolated(safe=0) is fast but inaccurate, because it + * doesn't account for the vm_stat_diff[] counters. So if it looks + * like too_many_isolated() is about to return true, fall back to the + * slower, more accurate zone_page_state_snapshot(). + */ + if (unlikely(__too_many_isolated(cc->zone, 0))) { + if (cc->mode != MIGRATE_ASYNC) + return __too_many_isolated(cc->zone, 1); + } + + return false; +} + /** * isolate_migratepages_block() - isolate all migrate-able pages within * a single pageblock @@ -686,7 +718,7 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn, * list by either parallel reclaimers or compaction. If there are, * delay for some time until fewer pages are isolated */ - while (unlikely(too_many_isolated(zone))) { + while (unlikely(too_many_isolated(cc))) { /* async migration should just abort */ if (cc->mode == MIGRATE_ASYNC) return 0;