aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorDavid Rientjes <rientjes@google.com>2007-10-17 02:25:56 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-17 11:42:45 -0400
commitff0ceb9deb6eb017f52900b708d49cfa77bf25fb (patch)
treeaa33fef12afb05cb2644e7ae38b79ef6dd8ba59d /mm
parent098d7f128a4e53cb64930628915ac767785e0e60 (diff)
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>
Diffstat (limited to 'mm')
-rw-r--r--mm/page_alloc.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index fd2df29cc645..43f757fcf30f 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1587,6 +1587,11 @@ nofail_alloc:
1587 if (page) 1587 if (page)
1588 goto got_pg; 1588 goto got_pg;
1589 } else if ((gfp_mask & __GFP_FS) && !(gfp_mask & __GFP_NORETRY)) { 1589 } else if ((gfp_mask & __GFP_FS) && !(gfp_mask & __GFP_NORETRY)) {
1590 if (!try_set_zone_oom(zonelist)) {
1591 schedule_timeout_uninterruptible(1);
1592 goto restart;
1593 }
1594
1590 /* 1595 /*
1591 * Go through the zonelist yet one more time, keep 1596 * Go through the zonelist yet one more time, keep
1592 * very high watermark here, this is only to catch 1597 * very high watermark here, this is only to catch
@@ -1595,14 +1600,19 @@ nofail_alloc:
1595 */ 1600 */
1596 page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, order, 1601 page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, order,
1597 zonelist, ALLOC_WMARK_HIGH|ALLOC_CPUSET); 1602 zonelist, ALLOC_WMARK_HIGH|ALLOC_CPUSET);
1598 if (page) 1603 if (page) {
1604 clear_zonelist_oom(zonelist);
1599 goto got_pg; 1605 goto got_pg;
1606 }
1600 1607
1601 /* The OOM killer will not help higher order allocs so fail */ 1608 /* The OOM killer will not help higher order allocs so fail */
1602 if (order > PAGE_ALLOC_COSTLY_ORDER) 1609 if (order > PAGE_ALLOC_COSTLY_ORDER) {
1610 clear_zonelist_oom(zonelist);
1603 goto nopage; 1611 goto nopage;
1612 }
1604 1613
1605 out_of_memory(zonelist, gfp_mask, order); 1614 out_of_memory(zonelist, gfp_mask, order);
1615 clear_zonelist_oom(zonelist);
1606 goto restart; 1616 goto restart;
1607 } 1617 }
1608 1618