aboutsummaryrefslogtreecommitdiff
path: root/mm/page_alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r--mm/page_alloc.c25
1 files changed, 19 insertions, 6 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 4025d9979..82a296ec2 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -281,6 +281,8 @@ void __meminit set_pageblock_mobility(struct page *page, int mobility)
}
#endif
+bool oom_killer_disabled __read_mostly;
+
#ifdef CONFIG_DEBUG_VM
static int page_outside_zone_boundaries(struct zone *zone, struct page *page)
{
@@ -2529,17 +2531,28 @@ __alloc_pages_may_oom(gfp_t gfp_mask, unsigned int order,
*did_some_progress = 0;
+ if (oom_killer_disabled)
+ return NULL;
+
/*
- * Acquire the oom lock. If that fails, somebody else is
- * making progress for us.
+ * Acquire the per-zone oom lock for each zone. If that
+ * fails, somebody else is making progress for us.
*/
- if (!mutex_trylock(&oom_lock)) {
+ if (!oom_zonelist_trylock(zonelist, gfp_mask)) {
*did_some_progress = 1;
schedule_timeout_uninterruptible(1);
return NULL;
}
/*
+ * PM-freezer should be notified that there might be an OOM killer on
+ * its way to kill and wake somebody up. This is too early and we might
+ * end up not killing anything but false positives are acceptable.
+ * See freeze_processes.
+ */
+ note_oom_kill();
+
+ /*
* Go through the zonelist yet one more time, keep very high watermark
* here, this is only to catch a parallel oom killing, we must fail if
* we're still under heavy pressure.
@@ -2575,10 +2588,10 @@ __alloc_pages_may_oom(gfp_t gfp_mask, unsigned int order,
goto out;
}
/* Exhausted what can be done so it's blamo time */
- if (out_of_memory(zonelist, gfp_mask, order, nodemask, false))
- *did_some_progress = 1;
+ out_of_memory(zonelist, gfp_mask, order, nodemask, false);
+ *did_some_progress = 1;
out:
- mutex_unlock(&oom_lock);
+ oom_zonelist_unlock(zonelist, gfp_mask);
return page;
}