提交 e46e7b77 编写于 作者: M Mel Gorman 提交者: Linus Torvalds

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: c33d6c06 ("mm, page_alloc: avoid looking up the first zone in a zonelist twice")
Signed-off-by: NMel Gorman <mgorman@techsingularity.net>
Reported-by: NGeert Uytterhoeven <geert@linux-m68k.org>
Tested-by: NGeert Uytterhoeven <geert@linux-m68k.org>
Acked-by: NVlastimil Babka <vbabka@suse.cz>
Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
上级 0d0bd894
...@@ -3604,6 +3604,17 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, ...@@ -3604,6 +3604,17 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
*/ */
alloc_flags = gfp_to_alloc_flags(gfp_mask); alloc_flags = gfp_to_alloc_flags(gfp_mask);
/*
* Reset the zonelist iterators if memory policies can be ignored.
* These allocations are high priority and system rather than user
* orientated.
*/
if ((alloc_flags & ALLOC_NO_WATERMARKS) || !(alloc_flags & ALLOC_CPUSET)) {
ac->zonelist = node_zonelist(numa_node_id(), gfp_mask);
ac->preferred_zoneref = first_zones_zonelist(ac->zonelist,
ac->high_zoneidx, ac->nodemask);
}
/* This is the last chance, in general, before the goto nopage. */ /* This is the last chance, in general, before the goto nopage. */
page = get_page_from_freelist(gfp_mask, order, page = get_page_from_freelist(gfp_mask, order,
alloc_flags & ~ALLOC_NO_WATERMARKS, ac); alloc_flags & ~ALLOC_NO_WATERMARKS, ac);
...@@ -3612,12 +3623,6 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, ...@@ -3612,12 +3623,6 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
/* Allocate without watermarks if the context allows */ /* Allocate without watermarks if the context allows */
if (alloc_flags & ALLOC_NO_WATERMARKS) { if (alloc_flags & ALLOC_NO_WATERMARKS) {
/*
* Ignore mempolicies if ALLOC_NO_WATERMARKS on the grounds
* the allocation is high priority and these type of
* allocations are system rather than user orientated
*/
ac->zonelist = node_zonelist(numa_node_id(), gfp_mask);
page = get_page_from_freelist(gfp_mask, order, page = get_page_from_freelist(gfp_mask, order,
ALLOC_NO_WATERMARKS, ac); ALLOC_NO_WATERMARKS, ac);
if (page) if (page)
...@@ -3816,7 +3821,11 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order, ...@@ -3816,7 +3821,11 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
/* Dirty zone balancing only done in the fast path */ /* Dirty zone balancing only done in the fast path */
ac.spread_dirty_pages = (gfp_mask & __GFP_WRITE); ac.spread_dirty_pages = (gfp_mask & __GFP_WRITE);
/* The preferred zone is used for statistics later */ /*
* The preferred zone is used for statistics but crucially it is
* also used as the starting point for the zonelist iterator. It
* may get reset for allocations that ignore memory policies.
*/
ac.preferred_zoneref = first_zones_zonelist(ac.zonelist, ac.preferred_zoneref = first_zones_zonelist(ac.zonelist,
ac.high_zoneidx, ac.nodemask); ac.high_zoneidx, ac.nodemask);
if (!ac.preferred_zoneref) { if (!ac.preferred_zoneref) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册