aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorJohannes Weiner <hannes@cmpxchg.org>2011-02-10 18:01:34 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-02-11 19:12:20 -0500
commitf0fdc5e8e6f579310458aef43d1610a0bb5e81a4 (patch)
treec3f9de434bf9065d2f1d7a5f4214f28efb4920c4 /mm
parent419d8c96dbfa558f00e623023917d0a5afc46129 (diff)
vmscan: fix zone shrinking exit when scan work is done
Commit 3e7d34497067 ("mm: vmscan: reclaim order-0 and use compaction instead of lumpy reclaim") introduced an indefinite loop in shrink_zone(). It meant to break out of this loop when no pages had been reclaimed and not a single page was even scanned. The way it would detect the latter is by taking a snapshot of sc->nr_scanned at the beginning of the function and comparing it against the new sc->nr_scanned after the scan loop. But it would re-iterate without updating that snapshot, looping forever if sc->nr_scanned changed at least once since shrink_zone() was invoked. This is not the sole condition that would exit that loop, but it requires other processes to change the zone state, as the reclaimer that is stuck obviously can not anymore. This is only happening for higher-order allocations, where reclaim is run back to back with compaction. Signed-off-by: Johannes Weiner <hannes@cmpxchg.org> Reported-by: Michal Hocko <mhocko@suse.cz> Tested-by: Kent Overstreet<kent.overstreet@gmail.com> Reported-by: Kent Overstreet <kent.overstreet@gmail.com> Acked-by: Mel Gorman <mel@csn.ul.ie> Cc: Andrea Arcangeli <aarcange@redhat.com> Cc: Rik van Riel <riel@redhat.com> Reviewed-by: Minchan Kim <minchan.kim@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/vmscan.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 148c6e630df2..17497d0cd8b9 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1882,12 +1882,12 @@ static void shrink_zone(int priority, struct zone *zone,
1882 unsigned long nr[NR_LRU_LISTS]; 1882 unsigned long nr[NR_LRU_LISTS];
1883 unsigned long nr_to_scan; 1883 unsigned long nr_to_scan;
1884 enum lru_list l; 1884 enum lru_list l;
1885 unsigned long nr_reclaimed; 1885 unsigned long nr_reclaimed, nr_scanned;
1886 unsigned long nr_to_reclaim = sc->nr_to_reclaim; 1886 unsigned long nr_to_reclaim = sc->nr_to_reclaim;
1887 unsigned long nr_scanned = sc->nr_scanned;
1888 1887
1889restart: 1888restart:
1890 nr_reclaimed = 0; 1889 nr_reclaimed = 0;
1890 nr_scanned = sc->nr_scanned;
1891 get_scan_count(zone, sc, nr, priority); 1891 get_scan_count(zone, sc, nr, priority);
1892 1892
1893 while (nr[LRU_INACTIVE_ANON] || nr[LRU_ACTIVE_FILE] || 1893 while (nr[LRU_INACTIVE_ANON] || nr[LRU_ACTIVE_FILE] ||