aboutsummaryrefslogtreecommitdiffstats
path: root/mm/page_alloc.c
diff options
context:
space:
mode:
authorMel Gorman <mgorman@suse.de>2013-04-29 18:07:57 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-04-29 18:54:35 -0400
commitfed2719e7a8612471bd17113ed326d38df434f17 (patch)
tree7c3c477ad75e885b68ccfcc473bffd6f9b9dcbea /mm/page_alloc.c
parent8e2cdbcb86b0abefc3d07922c48edb01fece3c56 (diff)
mm: page_alloc: avoid marking zones full prematurely after zone_reclaim()
The following problem was reported against a distribution kernel when zone_reclaim was enabled but the same problem applies to the mainline kernel. The reproduction case was as follows 1. Run numactl -m +0 dd if=largefile of=/dev/null This allocates a large number of clean pages in node 0 2. numactl -N +0 memhog 0.5*Mg This start a memory-using application in node 0. The expected behaviour is that the clean pages get reclaimed and the application uses node 0 for its memory. The observed behaviour was that the memory for the memhog application was allocated off-node since commits cd38b115d5ad ("mm: page allocator: initialise ZLC for first zone eligible for zone_reclaim") and commit 76d3fbf8fbf6 ("mm: page allocator: reconsider zones for allocation after direct reclaim"). The assumption of those patches was that it was always preferable to allocate quickly than stall for long periods of time and they were meant to take care that the zone was only marked full when necessary but an important case was missed. In the allocator fast path, only the low watermarks are checked. If the zones free pages are between the low and min watermark then allocations from the allocators slow path will succeed. However, zone_reclaim will only reclaim SWAP_CLUSTER_MAX or 1<<order pages. There is no guarantee that this will meet the low watermark causing the zone to be marked full prematurely. This patch will only mark the zone full after zone_reclaim if it the min watermarks are checked or if page reclaim failed to make sufficient progress. [mhocko@suse.cz: fix alloc_flags test] Signed-off-by: Mel Gorman <mgorman@suse.de> Reported-by: Hedi Berriche <hedi@sgi.com> Tested-by: Hedi Berriche <hedi@sgi.com> Reviewed-by: Michal Hocko <mhocko@suse.cz> Reviewed-by: Wanpeng Li <liwanp@linux.vnet.ibm.com> Signed-off-by: Michal Hocko <mhocko@suse.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r--mm/page_alloc.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 7350986bbf99..b54c5cbf0200 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1942,9 +1942,24 @@ zonelist_scan:
1942 continue; 1942 continue;
1943 default: 1943 default:
1944 /* did we reclaim enough */ 1944 /* did we reclaim enough */
1945 if (!zone_watermark_ok(zone, order, mark, 1945 if (zone_watermark_ok(zone, order, mark,
1946 classzone_idx, alloc_flags)) 1946 classzone_idx, alloc_flags))
1947 goto try_this_zone;
1948
1949 /*
1950 * Failed to reclaim enough to meet watermark.
1951 * Only mark the zone full if checking the min
1952 * watermark or if we failed to reclaim just
1953 * 1<<order pages or else the page allocator
1954 * fastpath will prematurely mark zones full
1955 * when the watermark is between the low and
1956 * min watermarks.
1957 */
1958 if (((alloc_flags & ALLOC_WMARK_MASK) == ALLOC_WMARK_MIN) ||
1959 ret == ZONE_RECLAIM_SOME)
1947 goto this_zone_full; 1960 goto this_zone_full;
1961
1962 continue;
1948 } 1963 }
1949 } 1964 }
1950 1965