mm: vmscan: do not continue scanning if reclaim was aborted for compaction
authorMel Gorman <mgorman@suse.de>
Mon, 8 Jul 2013 23:00:24 +0000 (16:00 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 9 Jul 2013 17:33:23 +0000 (10:33 -0700)
Direct reclaim is not aborting to allow compaction to go ahead properly.
do_try_to_free_pages is told to abort reclaim which is happily ignores
and instead increases priority instead until it reaches 0 and starts
shrinking file/anon equally.  This patch corrects the situation by
aborting reclaim when requested instead of raising priority.

Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: Rik van Riel <riel@redhat.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@suse.cz>
Cc: Dave Chinner <david@fromorbit.com>
Cc: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
mm/vmscan.c

index 99b3ac7..2385663 100644 (file)
@@ -2361,8 +2361,10 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist,
                aborted_reclaim = shrink_zones(zonelist, sc);
 
                /*
-                * Don't shrink slabs when reclaiming memory from
-                * over limit cgroups
+                * Don't shrink slabs when reclaiming memory from over limit
+                * cgroups but do shrink slab at least once when aborting
+                * reclaim for compaction to avoid unevenly scanning file/anon
+                * LRU pages over slab pages.
                 */
                if (global_reclaim(sc)) {
                        unsigned long lru_pages = 0;
@@ -2404,7 +2406,7 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist,
                                                WB_REASON_TRY_TO_FREE_PAGES);
                        sc->may_writepage = 1;
                }
-       } while (--sc->priority >= 0);
+       } while (--sc->priority >= 0 && !aborted_reclaim);
 
 out:
        delayacct_freepages_end();