diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 86349586eacbac5022affca24ebaa2b57d19aa15..32d8210b877329a42cc84a6b6d77f0f5b49da7c2 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -876,6 +876,15 @@ bool out_of_memory(struct oom_control *oc) return true; } + /* + * The OOM killer does not compensate for IO-less reclaim. + * pagefault_out_of_memory lost its gfp context so we have to + * make sure exclude 0 mask - all other users should have at least + * ___GFP_DIRECT_RECLAIM to get here. + */ + if (oc->gfp_mask && !(oc->gfp_mask & (__GFP_FS|__GFP_NOFAIL))) + return true; + /* * Check if there were limitations on the allocation (only relevant for * NUMA) that may require different handling. diff --git a/mm/page_alloc.c b/mm/page_alloc.c index da6d339f1936446f0feae1bf5e0843748f6d0f5e..6d1c8b06b45803afa0341edfcfae41ccee2574ab 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2875,22 +2875,18 @@ __alloc_pages_may_oom(gfp_t gfp_mask, unsigned int order, /* The OOM killer does not needlessly kill tasks for lowmem */ if (ac->high_zoneidx < ZONE_NORMAL) goto out; - /* The OOM killer does not compensate for IO-less reclaim */ - if (!(gfp_mask & __GFP_FS)) { - /* - * XXX: Page reclaim didn't yield anything, - * and the OOM killer can't be invoked, but - * keep looping as per tradition. - * - * But do not keep looping if oom_killer_disable() - * was already called, for the system is trying to - * enter a quiescent state during suspend. - */ - *did_some_progress = !oom_killer_disabled; - goto out; - } if (pm_suspended_storage()) goto out; + /* + * XXX: GFP_NOFS allocations should rather fail than rely on + * other request to make a forward progress. + * 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 + * access to memory reserved if the current task is killed (see + * out_of_memory). Once filesystems are ready to handle allocation + * 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;