Commit 06ad276a authored by Michal Hocko's avatar Michal Hocko Committed by Linus Torvalds

mm, oom: do not enforce OOM killer for __GFP_NOFAIL automatically

__alloc_pages_may_oom makes sure to skip the OOM killer depending on the
allocation request.  This includes lowmem requests, costly high order
requests and others.  For a long time __GFP_NOFAIL acted as an override
for all those rules.  This is not documented and it can be quite
surprising as well.  E.g.  GFP_NOFS requests are not invoking the OOM
killer but GFP_NOFS|__GFP_NOFAIL does so if we try to convert some of
the existing open coded loops around allocator to nofail request (and we
have done that in the past) then such a change would have a non trivial
side effect which is far from obvious.  Note that the primary motivation
for skipping the OOM killer is to prevent from pre-mature invocation.

The exception has been added by commit 82553a93 ("oom: invoke oom
killer for __GFP_NOFAIL").  The changelog points out that the oom killer
has to be invoked otherwise the request would be looping for ever.  But
this argument is rather weak because the OOM killer doesn't really
guarantee a forward progress for those exceptional cases:

- it will hardly help to form costly order which in turn can result in
  the system panic because of no oom killable task in the end - I believe
  we certainly do not want to put the system down just because there is a
  nasty driver asking for order-9 page with GFP_NOFAIL not realizing all
  the consequences.  It is much better this request would loop for ever
  than the massive system disruption

- lowmem is also highly unlikely to be freed during OOM killer

- GFP_NOFS request could trigger while there is still a lot of memory
  pinned by filesystems.

This patch simply removes the __GFP_NOFAIL special case in order to have a
more clear semantic without surprising side effects.
Signed-off-by: default avatarMichal Hocko <mhocko@suse.com>
Reported-by: default avatarNils Holland <nholland@tisys.org>
Acked-by: default avatarJohannes Weiner <hannes@cmpxchg.org>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Hillf Danton <hillf.zj@alibaba-inc.com>
Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 9a67f648
...@@ -1013,7 +1013,7 @@ bool out_of_memory(struct oom_control *oc) ...@@ -1013,7 +1013,7 @@ bool out_of_memory(struct oom_control *oc)
* make sure exclude 0 mask - all other users should have at least * make sure exclude 0 mask - all other users should have at least
* ___GFP_DIRECT_RECLAIM to get here. * ___GFP_DIRECT_RECLAIM to get here.
*/ */
if (oc->gfp_mask && !(oc->gfp_mask & (__GFP_FS|__GFP_NOFAIL))) if (oc->gfp_mask && !(oc->gfp_mask & __GFP_FS))
return true; return true;
/* /*
......
...@@ -3090,32 +3090,31 @@ __alloc_pages_may_oom(gfp_t gfp_mask, unsigned int order, ...@@ -3090,32 +3090,31 @@ __alloc_pages_may_oom(gfp_t gfp_mask, unsigned int order,
if (page) if (page)
goto out; goto out;
if (!(gfp_mask & __GFP_NOFAIL)) { /* Coredumps can quickly deplete all memory reserves */
/* Coredumps can quickly deplete all memory reserves */ if (current->flags & PF_DUMPCORE)
if (current->flags & PF_DUMPCORE) goto out;
goto out; /* The OOM killer will not help higher order allocs */
/* The OOM killer will not help higher order allocs */ if (order > PAGE_ALLOC_COSTLY_ORDER)
if (order > PAGE_ALLOC_COSTLY_ORDER) goto out;
goto out; /* The OOM killer does not needlessly kill tasks for lowmem */
/* The OOM killer does not needlessly kill tasks for lowmem */ if (ac->high_zoneidx < ZONE_NORMAL)
if (ac->high_zoneidx < ZONE_NORMAL) goto out;
goto out; if (pm_suspended_storage())
if (pm_suspended_storage()) goto out;
goto out; /*
/* * XXX: GFP_NOFS allocations should rather fail than rely on
* XXX: GFP_NOFS allocations should rather fail than rely on * other request to make a forward progress.
* other request to make a forward progress. * We are in an unfortunate situation where out_of_memory cannot
* We are in an unfortunate situation where out_of_memory cannot * do much for this context but let's try it to at least get
* do much for this context but let's try it to at least get * access to memory reserved if the current task is killed (see
* access to memory reserved if the current task is killed (see * out_of_memory). Once filesystems are ready to handle allocation
* out_of_memory). Once filesystems are ready to handle allocation * failures more gracefully we should just bail out here.
* failures more gracefully we should just bail out here. */
*/
/* The OOM killer may not free memory on a specific node */
if (gfp_mask & __GFP_THISNODE)
goto out;
/* The OOM killer may not free memory on a specific node */
if (gfp_mask & __GFP_THISNODE)
goto out;
}
/* Exhausted what can be done so it's blamo time */ /* Exhausted what can be done so it's blamo time */
if (out_of_memory(&oc) || WARN_ON_ONCE(gfp_mask & __GFP_NOFAIL)) { if (out_of_memory(&oc) || WARN_ON_ONCE(gfp_mask & __GFP_NOFAIL)) {
*did_some_progress = 1; *did_some_progress = 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment