Skip to content

Commit 9a67f64

Browse files
Michal Hockotorvalds
authored andcommitted
mm: consolidate GFP_NOFAIL checks in the allocator slowpath
Tetsuo Handa has pointed out that commit 0a0337e ("mm, oom: rework oom detection") has subtly changed semantic for costly high order requests with __GFP_NOFAIL and withtout __GFP_REPEAT and those can fail right now. My code inspection didn't reveal any such users in the tree but it is true that this might lead to unexpected allocation failures and subsequent OOPs. __alloc_pages_slowpath wrt. GFP_NOFAIL is hard to follow currently. There are few special cases but we are lacking a catch all place to be sure we will not miss any case where the non failing allocation might fail. This patch reorganizes the code a bit and puts all those special cases under nopage label which is the generic go-to-fail path. Non failing allocations are retried or those that cannot retry like non-sleeping allocation go to the failure point directly. This should make the code flow much easier to follow and make it less error prone for future changes. While we are there we have to move the stall check up to catch potentially looping non-failing allocations. [[email protected]: fix alloc_flags may-be-used-uninitalized] Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Michal Hocko <[email protected]> Acked-by: Vlastimil Babka <[email protected]> Acked-by: Johannes Weiner <[email protected]> Acked-by: Hillf Danton <[email protected]> Cc: Tetsuo Handa <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 9af744d commit 9a67f64

File tree

1 file changed

+52
-39
lines changed

1 file changed

+52
-39
lines changed

mm/page_alloc.c

Lines changed: 52 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3577,6 +3577,14 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
35773577
no_progress_loops = 0;
35783578
compact_priority = DEF_COMPACT_PRIORITY;
35793579
cpuset_mems_cookie = read_mems_allowed_begin();
3580+
3581+
/*
3582+
* The fast path uses conservative alloc_flags to succeed only until
3583+
* kswapd needs to be woken up, and to avoid the cost of setting up
3584+
* alloc_flags precisely. So we do that now.
3585+
*/
3586+
alloc_flags = gfp_to_alloc_flags(gfp_mask);
3587+
35803588
/*
35813589
* We need to recalculate the starting point for the zonelist iterator
35823590
* because we might have used different nodemask in the fast path, or
@@ -3588,14 +3596,6 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
35883596
if (!ac->preferred_zoneref->zone)
35893597
goto nopage;
35903598

3591-
3592-
/*
3593-
* The fast path uses conservative alloc_flags to succeed only until
3594-
* kswapd needs to be woken up, and to avoid the cost of setting up
3595-
* alloc_flags precisely. So we do that now.
3596-
*/
3597-
alloc_flags = gfp_to_alloc_flags(gfp_mask);
3598-
35993599
if (gfp_mask & __GFP_KSWAPD_RECLAIM)
36003600
wake_all_kswapds(order, ac);
36013601

@@ -3672,35 +3672,21 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
36723672
goto got_pg;
36733673

36743674
/* Caller is not willing to reclaim, we can't balance anything */
3675-
if (!can_direct_reclaim) {
3676-
/*
3677-
* All existing users of the __GFP_NOFAIL are blockable, so warn
3678-
* of any new users that actually allow this type of allocation
3679-
* to fail.
3680-
*/
3681-
WARN_ON_ONCE(gfp_mask & __GFP_NOFAIL);
3675+
if (!can_direct_reclaim)
36823676
goto nopage;
3683-
}
36843677

3685-
/* Avoid recursion of direct reclaim */
3686-
if (current->flags & PF_MEMALLOC) {
3687-
/*
3688-
* __GFP_NOFAIL request from this context is rather bizarre
3689-
* because we cannot reclaim anything and only can loop waiting
3690-
* for somebody to do a work for us.
3691-
*/
3692-
if (WARN_ON_ONCE(gfp_mask & __GFP_NOFAIL)) {
3693-
cond_resched();
3694-
goto retry;
3695-
}
3696-
goto nopage;
3678+
/* Make sure we know about allocations which stall for too long */
3679+
if (time_after(jiffies, alloc_start + stall_timeout)) {
3680+
warn_alloc(gfp_mask, ac->nodemask,
3681+
"page allocation stalls for %ums, order:%u",
3682+
jiffies_to_msecs(jiffies-alloc_start), order);
3683+
stall_timeout += 10 * HZ;
36973684
}
36983685

3699-
/* Avoid allocations with no watermarks from looping endlessly */
3700-
if (test_thread_flag(TIF_MEMDIE) && !(gfp_mask & __GFP_NOFAIL))
3686+
/* Avoid recursion of direct reclaim */
3687+
if (current->flags & PF_MEMALLOC)
37013688
goto nopage;
37023689

3703-
37043690
/* Try direct reclaim and then allocating */
37053691
page = __alloc_pages_direct_reclaim(gfp_mask, order, alloc_flags, ac,
37063692
&did_some_progress);
@@ -3724,14 +3710,6 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
37243710
if (order > PAGE_ALLOC_COSTLY_ORDER && !(gfp_mask & __GFP_REPEAT))
37253711
goto nopage;
37263712

3727-
/* Make sure we know about allocations which stall for too long */
3728-
if (time_after(jiffies, alloc_start + stall_timeout)) {
3729-
warn_alloc(gfp_mask, ac->nodemask,
3730-
"page allocation stalls for %ums, order:%u",
3731-
jiffies_to_msecs(jiffies-alloc_start), order);
3732-
stall_timeout += 10 * HZ;
3733-
}
3734-
37353713
if (should_reclaim_retry(gfp_mask, order, ac, alloc_flags,
37363714
did_some_progress > 0, &no_progress_loops))
37373715
goto retry;
@@ -3760,6 +3738,10 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
37603738
if (page)
37613739
goto got_pg;
37623740

3741+
/* Avoid allocations with no watermarks from looping endlessly */
3742+
if (test_thread_flag(TIF_MEMDIE))
3743+
goto nopage;
3744+
37633745
/* Retry as long as the OOM killer is making progress */
37643746
if (did_some_progress) {
37653747
no_progress_loops = 0;
@@ -3777,6 +3759,37 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
37773759
if (read_mems_allowed_retry(cpuset_mems_cookie))
37783760
goto retry_cpuset;
37793761

3762+
/*
3763+
* Make sure that __GFP_NOFAIL request doesn't leak out and make sure
3764+
* we always retry
3765+
*/
3766+
if (gfp_mask & __GFP_NOFAIL) {
3767+
/*
3768+
* All existing users of the __GFP_NOFAIL are blockable, so warn
3769+
* of any new users that actually require GFP_NOWAIT
3770+
*/
3771+
if (WARN_ON_ONCE(!can_direct_reclaim))
3772+
goto fail;
3773+
3774+
/*
3775+
* PF_MEMALLOC request from this context is rather bizarre
3776+
* because we cannot reclaim anything and only can loop waiting
3777+
* for somebody to do a work for us
3778+
*/
3779+
WARN_ON_ONCE(current->flags & PF_MEMALLOC);
3780+
3781+
/*
3782+
* non failing costly orders are a hard requirement which we
3783+
* are not prepared for much so let's warn about these users
3784+
* so that we can identify them and convert them to something
3785+
* else.
3786+
*/
3787+
WARN_ON_ONCE(order > PAGE_ALLOC_COSTLY_ORDER);
3788+
3789+
cond_resched();
3790+
goto retry;
3791+
}
3792+
fail:
37803793
warn_alloc(gfp_mask, ac->nodemask,
37813794
"page allocation failure: order:%u", order);
37823795
got_pg:

0 commit comments

Comments
 (0)