oom: serialize out of memory calls
A final allocation attempt with a very high watermark needs to be attempted before invoking out_of_memory(). OOM killer serialization needs to occur before this final attempt, otherwise tasks attempting to OOM-lock all zones in its zonelist may spin and acquire the lock unnecessarily after the OOM condition has already been alleviated. If the final allocation does succeed, the zonelist is simply OOM-unlocked and __alloc_pages() returns the page. Otherwise, the OOM killer is invoked. If the task cannot acquire OOM-locks on all zones in its zonelist, it is put to sleep and the allocation is retried when it gets rescheduled. One of its zones is already marked as being in the OOM killer so it'll hopefully be getting some free memory soon, at least enough to satisfy a high watermark allocation attempt. This prevents needlessly killing a task when the OOM condition would have already been alleviated if it had simply been given enough time. Cc: Andrea Arcangeli <andrea@suse.de> Acked-by: Christoph Lameter <clameter@sgi.com> Signed-off-by: David Rientjes <rientjes@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
098d7f128a
commit
ff0ceb9deb
@ -1587,6 +1587,11 @@ nofail_alloc:
|
||||
if (page)
|
||||
goto got_pg;
|
||||
} else if ((gfp_mask & __GFP_FS) && !(gfp_mask & __GFP_NORETRY)) {
|
||||
if (!try_set_zone_oom(zonelist)) {
|
||||
schedule_timeout_uninterruptible(1);
|
||||
goto restart;
|
||||
}
|
||||
|
||||
/*
|
||||
* Go through the zonelist yet one more time, keep
|
||||
* very high watermark here, this is only to catch
|
||||
@ -1595,14 +1600,19 @@ nofail_alloc:
|
||||
*/
|
||||
page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, order,
|
||||
zonelist, ALLOC_WMARK_HIGH|ALLOC_CPUSET);
|
||||
if (page)
|
||||
if (page) {
|
||||
clear_zonelist_oom(zonelist);
|
||||
goto got_pg;
|
||||
}
|
||||
|
||||
/* The OOM killer will not help higher order allocs so fail */
|
||||
if (order > PAGE_ALLOC_COSTLY_ORDER)
|
||||
if (order > PAGE_ALLOC_COSTLY_ORDER) {
|
||||
clear_zonelist_oom(zonelist);
|
||||
goto nopage;
|
||||
}
|
||||
|
||||
out_of_memory(zonelist, gfp_mask, order);
|
||||
clear_zonelist_oom(zonelist);
|
||||
goto restart;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user