summaryrefslogtreecommitdiffstats
path: root/mm/page_alloc.c
diff options
context:
space:
mode:
authorVlastimil Babka <vbabka@suse.cz>2016-07-28 18:49:16 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-07-28 19:07:41 -0400
commit23771235bb569c4999ff077d2c38eaee5763193a (patch)
tree9a1c7884af634c7266dda359bec844c98cd1880c /mm/page_alloc.c
parent31a6c1909f51dbe9bf08eb40dc64e3db90cf6f79 (diff)
mm, page_alloc: don't retry initial attempt in slowpath
After __alloc_pages_slowpath() sets up new alloc_flags and wakes up kswapd, it first tries get_page_from_freelist() with the new alloc_flags, as it may succeed e.g. due to using min watermark instead of low watermark. It makes sense to to do this attempt before adjusting zonelist based on alloc_flags/gfp_mask, as it's still relatively a fast path if we just wake up kswapd and successfully allocate. This patch therefore moves the initial attempt above the retry label and reorganizes a bit the part below the retry label. We still have to attempt get_page_from_freelist() on each retry, as some allocations cannot do that as part of direct reclaim or compaction, and yet are not allowed to fail (even though they do a WARN_ON_ONCE() and thus should not exist). We can reuse the call meant for ALLOC_NO_WATERMARKS attempt and just set alloc_flags to ALLOC_NO_WATERMARKS if the context allows it. As a side-effect, the attempts from direct reclaim/compaction will also no longer obey watermarks once this is set, but there's little harm in that. Kswapd wakeups are also done on each retry to be safe from potential races resulting in kswapd going to sleep while a process (that may not be able to reclaim by itself) is still looping. Link: http://lkml.kernel.org/r/20160721073614.24395-4-vbabka@suse.cz Signed-off-by: Vlastimil Babka <vbabka@suse.cz> Acked-by: Michal Hocko <mhocko@suse.com> Acked-by: Mel Gorman <mgorman@techsingularity.net> Acked-by: David Rientjes <rientjes@google.com> 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.c29
1 files changed, 18 insertions, 11 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 5703f7fca832..a42fa09ee91f 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -3510,35 +3510,42 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
3510 */ 3510 */
3511 alloc_flags = gfp_to_alloc_flags(gfp_mask); 3511 alloc_flags = gfp_to_alloc_flags(gfp_mask);
3512 3512
3513 if (gfp_mask & __GFP_KSWAPD_RECLAIM)
3514 wake_all_kswapds(order, ac);
3515
3516 /*
3517 * The adjusted alloc_flags might result in immediate success, so try
3518 * that first
3519 */
3520 page = get_page_from_freelist(gfp_mask, order, alloc_flags, ac);
3521 if (page)
3522 goto got_pg;
3523
3524
3513retry: 3525retry:
3526 /* Ensure kswapd doesn't accidentally go to sleep as long as we loop */
3514 if (gfp_mask & __GFP_KSWAPD_RECLAIM) 3527 if (gfp_mask & __GFP_KSWAPD_RECLAIM)
3515 wake_all_kswapds(order, ac); 3528 wake_all_kswapds(order, ac);
3516 3529
3530 if (gfp_pfmemalloc_allowed(gfp_mask))
3531 alloc_flags = ALLOC_NO_WATERMARKS;
3532
3517 /* 3533 /*
3518 * Reset the zonelist iterators if memory policies can be ignored. 3534 * Reset the zonelist iterators if memory policies can be ignored.
3519 * These allocations are high priority and system rather than user 3535 * These allocations are high priority and system rather than user
3520 * orientated. 3536 * orientated.
3521 */ 3537 */
3522 if (!(alloc_flags & ALLOC_CPUSET) || gfp_pfmemalloc_allowed(gfp_mask)) { 3538 if (!(alloc_flags & ALLOC_CPUSET) || (alloc_flags & ALLOC_NO_WATERMARKS)) {
3523 ac->zonelist = node_zonelist(numa_node_id(), gfp_mask); 3539 ac->zonelist = node_zonelist(numa_node_id(), gfp_mask);
3524 ac->preferred_zoneref = first_zones_zonelist(ac->zonelist, 3540 ac->preferred_zoneref = first_zones_zonelist(ac->zonelist,
3525 ac->high_zoneidx, ac->nodemask); 3541 ac->high_zoneidx, ac->nodemask);
3526 } 3542 }
3527 3543
3528 /* This is the last chance, in general, before the goto nopage. */ 3544 /* Attempt with potentially adjusted zonelist and alloc_flags */
3529 page = get_page_from_freelist(gfp_mask, order, alloc_flags, ac); 3545 page = get_page_from_freelist(gfp_mask, order, alloc_flags, ac);
3530 if (page) 3546 if (page)
3531 goto got_pg; 3547 goto got_pg;
3532 3548
3533 /* Allocate without watermarks if the context allows */
3534 if (gfp_pfmemalloc_allowed(gfp_mask)) {
3535
3536 page = get_page_from_freelist(gfp_mask, order,
3537 ALLOC_NO_WATERMARKS, ac);
3538 if (page)
3539 goto got_pg;
3540 }
3541
3542 /* Caller is not willing to reclaim, we can't balance anything */ 3549 /* Caller is not willing to reclaim, we can't balance anything */
3543 if (!can_direct_reclaim) { 3550 if (!can_direct_reclaim) {
3544 /* 3551 /*