aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorMel Gorman <mgorman@techsingularity.net>2016-06-03 17:56:01 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-06-03 19:02:57 -0400
commite46e7b77c9096eb2f4d6bcb9ca0b64c9338465ee (patch)
tree8c38e587733ee50aa021e03e8395274c5ce1fbb5 /mm
parent0d0bd89435d19faa3f2fd73f7ee11c64ac9304f4 (diff)
mm, page_alloc: recalculate the preferred zoneref if the context can ignore memory policies
The optimistic fast path may use cpuset_current_mems_allowed instead of of a NULL nodemask supplied by the caller for cpuset allocations. The preferred zone is calculated on this basis for statistic purposes and as a starting point in the zonelist iterator. However, if the context can ignore memory policies due to being atomic or being able to ignore watermarks then the starting point in the zonelist iterator is no longer correct. This patch resets the zonelist iterator in the allocator slowpath if the context can ignore memory policies. This will alter the zone used for statistics but only after it is known that it makes sense for that context. Resetting it before entering the slowpath would potentially allow an ALLOC_CPUSET allocation to be accounted for against the wrong zone. Note that while nodemask is not explicitly set to the original nodemask, it would only have been overwritten if cpuset_enabled() and it was reset before the slowpath was entered. Link: http://lkml.kernel.org/r/20160602103936.GU2527@techsingularity.net Fixes: c33d6c06f60f710 ("mm, page_alloc: avoid looking up the first zone in a zonelist twice") Signed-off-by: Mel Gorman <mgorman@techsingularity.net> Reported-by: Geert Uytterhoeven <geert@linux-m68k.org> Tested-by: Geert Uytterhoeven <geert@linux-m68k.org> Acked-by: Vlastimil Babka <vbabka@suse.cz> 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/page_alloc.c23
1 files changed, 16 insertions, 7 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 62d1ea3f2f5a..6903b695ebae 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -3604,6 +3604,17 @@ retry:
3604 */ 3604 */
3605 alloc_flags = gfp_to_alloc_flags(gfp_mask); 3605 alloc_flags = gfp_to_alloc_flags(gfp_mask);
3606 3606
3607 /*
3608 * Reset the zonelist iterators if memory policies can be ignored.
3609 * These allocations are high priority and system rather than user
3610 * orientated.
3611 */
3612 if ((alloc_flags & ALLOC_NO_WATERMARKS) || !(alloc_flags & ALLOC_CPUSET)) {
3613 ac->zonelist = node_zonelist(numa_node_id(), gfp_mask);
3614 ac->preferred_zoneref = first_zones_zonelist(ac->zonelist,
3615 ac->high_zoneidx, ac->nodemask);
3616 }
3617
3607 /* This is the last chance, in general, before the goto nopage. */ 3618 /* This is the last chance, in general, before the goto nopage. */
3608 page = get_page_from_freelist(gfp_mask, order, 3619 page = get_page_from_freelist(gfp_mask, order,
3609 alloc_flags & ~ALLOC_NO_WATERMARKS, ac); 3620 alloc_flags & ~ALLOC_NO_WATERMARKS, ac);
@@ -3612,12 +3623,6 @@ retry:
3612 3623
3613 /* Allocate without watermarks if the context allows */ 3624 /* Allocate without watermarks if the context allows */
3614 if (alloc_flags & ALLOC_NO_WATERMARKS) { 3625 if (alloc_flags & ALLOC_NO_WATERMARKS) {
3615 /*
3616 * Ignore mempolicies if ALLOC_NO_WATERMARKS on the grounds
3617 * the allocation is high priority and these type of
3618 * allocations are system rather than user orientated
3619 */
3620 ac->zonelist = node_zonelist(numa_node_id(), gfp_mask);
3621 page = get_page_from_freelist(gfp_mask, order, 3626 page = get_page_from_freelist(gfp_mask, order,
3622 ALLOC_NO_WATERMARKS, ac); 3627 ALLOC_NO_WATERMARKS, ac);
3623 if (page) 3628 if (page)
@@ -3816,7 +3821,11 @@ retry_cpuset:
3816 /* Dirty zone balancing only done in the fast path */ 3821 /* Dirty zone balancing only done in the fast path */
3817 ac.spread_dirty_pages = (gfp_mask & __GFP_WRITE); 3822 ac.spread_dirty_pages = (gfp_mask & __GFP_WRITE);
3818 3823
3819 /* The preferred zone is used for statistics later */ 3824 /*
3825 * The preferred zone is used for statistics but crucially it is
3826 * also used as the starting point for the zonelist iterator. It
3827 * may get reset for allocations that ignore memory policies.
3828 */
3820 ac.preferred_zoneref = first_zones_zonelist(ac.zonelist, 3829 ac.preferred_zoneref = first_zones_zonelist(ac.zonelist,
3821 ac.high_zoneidx, ac.nodemask); 3830 ac.high_zoneidx, ac.nodemask);
3822 if (!ac.preferred_zoneref) { 3831 if (!ac.preferred_zoneref) {