| From ae8624b1d6bb8c137f8564ee242e8ef4848d55f9 Mon Sep 17 00:00:00 2001 |
| From: Ming Ling <ming.ling@spreadtrum.com> |
| Date: Mon, 12 Dec 2016 16:42:26 -0800 |
| Subject: [PATCH] mm, compaction: fix NR_ISOLATED_* stats for pfn based |
| migration |
| |
| commit 6afcf8ef0ca0a69d014f8edb613d94821f0ae700 upstream. |
| |
| Since commit bda807d44454 ("mm: migrate: support non-lru movable page |
| migration") isolate_migratepages_block) can isolate !PageLRU pages which |
| would acct_isolated account as NR_ISOLATED_*. Accounting these non-lru |
| pages NR_ISOLATED_{ANON,FILE} doesn't make any sense and it can misguide |
| heuristics based on those counters such as pgdat_reclaimable_pages resp. |
| too_many_isolated which would lead to unexpected stalls during the |
| direct reclaim without any good reason. Note that |
| __alloc_contig_migrate_range can isolate a lot of pages at once. |
| |
| On mobile devices such as 512M ram android Phone, it may use a big zram |
| swap. In some cases zram(zsmalloc) uses too many non-lru but |
| migratedable pages, such as: |
| |
| MemTotal: 468148 kB |
| Normal free:5620kB |
| Free swap:4736kB |
| Total swap:409596kB |
| ZRAM: 164616kB(zsmalloc non-lru pages) |
| active_anon:60700kB |
| inactive_anon:60744kB |
| active_file:34420kB |
| inactive_file:37532kB |
| |
| Fix this by only accounting lru pages to NR_ISOLATED_* in |
| isolate_migratepages_block right after they were isolated and we still |
| know they were on LRU. Drop acct_isolated because it is called after |
| the fact and we've lost that information. Batching per-cpu counter |
| doesn't make much improvement anyway. Also make sure that we uncharge |
| only LRU pages when putting them back on the LRU in |
| putback_movable_pages resp. when unmap_and_move migrates the page. |
| |
| [mhocko@suse.com: replace acct_isolated() with direct counting] |
| Fixes: bda807d44454 ("mm: migrate: support non-lru movable page migration") |
| Link: http://lkml.kernel.org/r/20161019080240.9682-1-mhocko@kernel.org |
| Signed-off-by: Ming Ling <ming.ling@spreadtrum.com> |
| Signed-off-by: Michal Hocko <mhocko@suse.com> |
| Acked-by: Minchan Kim <minchan@kernel.org> |
| Acked-by: Vlastimil Babka <vbabka@suse.cz> |
| Cc: Mel Gorman <mgorman@suse.de> |
| Cc: Joonsoo Kim <js1304@gmail.com> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/mm/compaction.c b/mm/compaction.c |
| index 9affb2908304..187a12b5a4cf 100644 |
| --- a/mm/compaction.c |
| +++ b/mm/compaction.c |
| @@ -634,22 +634,6 @@ isolate_freepages_range(struct compact_control *cc, |
| return pfn; |
| } |
| |
| -/* Update the number of anon and file isolated pages in the zone */ |
| -static void acct_isolated(struct zone *zone, struct compact_control *cc) |
| -{ |
| - struct page *page; |
| - unsigned int count[2] = { 0, }; |
| - |
| - if (list_empty(&cc->migratepages)) |
| - return; |
| - |
| - list_for_each_entry(page, &cc->migratepages, lru) |
| - count[!!page_is_file_cache(page)]++; |
| - |
| - mod_node_page_state(zone->zone_pgdat, NR_ISOLATED_ANON, count[0]); |
| - mod_node_page_state(zone->zone_pgdat, NR_ISOLATED_FILE, count[1]); |
| -} |
| - |
| /* Similar to reclaim, but different enough that they don't share logic */ |
| static bool too_many_isolated(struct zone *zone) |
| { |
| @@ -866,6 +850,8 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn, |
| |
| /* Successfully isolated */ |
| del_page_from_lru_list(page, lruvec, page_lru(page)); |
| + inc_node_page_state(page, |
| + NR_ISOLATED_ANON + page_is_file_cache(page)); |
| |
| isolate_success: |
| list_add(&page->lru, &cc->migratepages); |
| @@ -902,7 +888,6 @@ isolate_fail: |
| spin_unlock_irqrestore(zone_lru_lock(zone), flags); |
| locked = false; |
| } |
| - acct_isolated(zone, cc); |
| putback_movable_pages(&cc->migratepages); |
| cc->nr_migratepages = 0; |
| cc->last_migrated_pfn = 0; |
| @@ -988,7 +973,6 @@ isolate_migratepages_range(struct compact_control *cc, unsigned long start_pfn, |
| if (cc->nr_migratepages == COMPACT_CLUSTER_MAX) |
| break; |
| } |
| - acct_isolated(cc->zone, cc); |
| |
| return pfn; |
| } |
| @@ -1254,10 +1238,8 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone, |
| low_pfn = isolate_migratepages_block(cc, low_pfn, |
| block_end_pfn, isolate_mode); |
| |
| - if (!low_pfn || cc->contended) { |
| - acct_isolated(zone, cc); |
| + if (!low_pfn || cc->contended) |
| return ISOLATE_ABORT; |
| - } |
| |
| /* |
| * Either we isolated something and proceed with migration. Or |
| @@ -1267,7 +1249,6 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone, |
| break; |
| } |
| |
| - acct_isolated(zone, cc); |
| /* Record where migration scanner will be restarted. */ |
| cc->migrate_pfn = low_pfn; |
| |
| diff --git a/mm/migrate.c b/mm/migrate.c |
| index f7ee04a5ae27..2469caa9156f 100644 |
| --- a/mm/migrate.c |
| +++ b/mm/migrate.c |
| @@ -168,8 +168,6 @@ void putback_movable_pages(struct list_head *l) |
| continue; |
| } |
| list_del(&page->lru); |
| - dec_node_page_state(page, NR_ISOLATED_ANON + |
| - page_is_file_cache(page)); |
| /* |
| * We isolated non-lru movable page so here we can use |
| * __PageMovable because LRU page's mapping cannot have |
| @@ -186,6 +184,8 @@ void putback_movable_pages(struct list_head *l) |
| put_page(page); |
| } else { |
| putback_lru_page(page); |
| + dec_node_page_state(page, NR_ISOLATED_ANON + |
| + page_is_file_cache(page)); |
| } |
| } |
| } |
| @@ -1121,8 +1121,15 @@ out: |
| * restored. |
| */ |
| list_del(&page->lru); |
| - dec_node_page_state(page, NR_ISOLATED_ANON + |
| - page_is_file_cache(page)); |
| + |
| + /* |
| + * Compaction can migrate also non-LRU pages which are |
| + * not accounted to NR_ISOLATED_*. They can be recognized |
| + * as __PageMovable |
| + */ |
| + if (likely(!__PageMovable(page))) |
| + dec_node_page_state(page, NR_ISOLATED_ANON + |
| + page_is_file_cache(page)); |
| } |
| |
| /* |
| -- |
| 2.10.1 |
| |