From: David Rientjes <rientjes@google.com>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: Andrea Arcangeli <andrea@suse.de>,
Christoph Lameter <clameter@sgi.com>,
Rik van Riel <riel@redhat.com>,
linux-mm@kvack.org
Subject: [patch 4/9] oom: add per-zone locking
Date: Thu, 20 Sep 2007 13:23:18 -0700 (PDT) [thread overview]
Message-ID: <alpine.DEB.0.9999.0709201321070.25753@chino.kir.corp.google.com> (raw)
In-Reply-To: <alpine.DEB.0.9999.0709201320521.25753@chino.kir.corp.google.com>
OOM killer synchronization should be done with zone granularity so that
memory policy and cpuset allocations may have their corresponding zones
locked and allow parallel kills for other OOM conditions that may exist
elsewhere in the system. DMA allocations can be targeted at the zone
level, which would not be possible if locking was done in nodes or
globally.
Synchronization shall be done with a variation of "trylocks." The goal
is to put the current task to sleep and restart the failed allocation
attempt later if the trylock fails. Otherwise, the OOM killer is
invoked.
Each zone in the zonelist that __alloc_pages() was called with is checked
for the newly-introduced ZONE_OOM_LOCKED flag. If any zone has this flag
present, the "trylock" to serialize the OOM killer fails and returns
zero. Otherwise, all the zones have ZONE_OOM_LOCKED set and the
try_set_zone_oom() function returns non-zero.
Cc: Andrea Arcangeli <andrea@suse.de>
Cc: Christoph Lameter <clameter@sgi.com>
Signed-off-by: David Rientjes <rientjes@google.com>
---
include/linux/mmzone.h | 5 ++++
include/linux/oom.h | 3 ++
mm/oom_kill.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 60 insertions(+), 0 deletions(-)
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -313,6 +313,7 @@ struct zone {
typedef enum {
ZONE_ALL_UNRECLAIMABLE, /* all pages pinned */
ZONE_RECLAIM_LOCKED, /* prevents concurrent reclaim */
+ ZONE_OOM_LOCKED, /* zone is in OOM killer zonelist */
} zone_flags_t;
static inline void zone_set_flag(struct zone *zone, zone_flags_t flag)
@@ -332,6 +333,10 @@ static inline int zone_is_reclaim_locked(const struct zone *zone)
{
return test_bit(ZONE_RECLAIM_LOCKED, &zone->flags);
}
+static inline int zone_is_oom_locked(const struct zone *zone)
+{
+ return test_bit(ZONE_OOM_LOCKED, &zone->flags);
+}
/*
* The "priority" of VM scanning is how much of the queues we will scan in one
diff --git a/include/linux/oom.h b/include/linux/oom.h
--- a/include/linux/oom.h
+++ b/include/linux/oom.h
@@ -20,6 +20,9 @@ enum oom_constraint {
CONSTRAINT_MEMORY_POLICY,
};
+extern int try_set_zone_oom(struct zonelist *zonelist);
+extern void clear_zonelist_oom(struct zonelist *zonelist);
+
extern void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order);
extern int register_oom_notifier(struct notifier_block *nb);
extern int unregister_oom_notifier(struct notifier_block *nb);
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -27,6 +27,7 @@
#include <linux/notifier.h>
int sysctl_panic_on_oom;
+static DEFINE_MUTEX(zone_scan_mutex);
/* #define DEBUG */
/**
@@ -381,6 +382,57 @@ int unregister_oom_notifier(struct notifier_block *nb)
}
EXPORT_SYMBOL_GPL(unregister_oom_notifier);
+/*
+ * Try to acquire the OOM killer lock for the zones in zonelist. Returns zero
+ * if a parallel OOM killing is already taking place that includes a zone in
+ * the zonelist. Otherwise, locks all zones in the zonelist and returns 1.
+ */
+int try_set_zone_oom(struct zonelist *zonelist)
+{
+ struct zone **z;
+ int ret = 1;
+
+ z = zonelist->zones;
+
+ mutex_lock(&zone_scan_mutex);
+ do {
+ if (zone_is_oom_locked(*z)) {
+ ret = 0;
+ goto out;
+ }
+ } while (*(++z) != NULL);
+
+ /*
+ * Lock each zone in the zonelist under zone_scan_mutex so a parallel
+ * invocation of try_set_zone_oom() doesn't succeed when it shouldn't.
+ */
+ z = zonelist->zones;
+ do {
+ zone_set_flag(*z, ZONE_OOM_LOCKED);
+ } while (*(++z) != NULL);
+out:
+ mutex_unlock(&zone_scan_mutex);
+ return ret;
+}
+
+/*
+ * Clears the ZONE_OOM_LOCKED flag for all zones in the zonelist so that failed
+ * allocation attempts with zonelists containing them may now recall the OOM
+ * killer, if necessary.
+ */
+void clear_zonelist_oom(struct zonelist *zonelist)
+{
+ struct zone **z;
+
+ z = zonelist->zones;
+
+ mutex_lock(&zone_scan_mutex);
+ do {
+ zone_clear_flag(*z, ZONE_OOM_LOCKED);
+ } while (*(++z) != NULL);
+ mutex_unlock(&zone_scan_mutex);
+}
+
/**
* out_of_memory - kill the "best" process when we run out of memory
*
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
next prev parent reply other threads:[~2007-09-20 20:23 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-09-20 20:23 [patch 0/9] oom killer serialization David Rientjes
2007-09-20 20:23 ` [patch 1/9] oom: move prototypes to appropriate header file David Rientjes
2007-09-20 20:23 ` [patch 2/9] oom: move constraints to enum David Rientjes
2007-09-20 20:23 ` [patch 3/9] oom: change all_unreclaimable zone member to flags David Rientjes
2007-09-20 20:23 ` David Rientjes [this message]
2007-09-20 20:23 ` [patch 5/9] oom: serialize out of memory calls David Rientjes
2007-09-20 20:23 ` [patch 6/9] oom: add oom_kill_asking_task sysctl David Rientjes
2007-09-20 20:23 ` [patch 7/9] oom: suppress extraneous stack and memory dump David Rientjes
2007-09-20 20:23 ` [patch 8/9] oom: compare cpuset mems_allowed instead of exclusive ancestors David Rientjes
2007-09-20 20:23 ` [patch 9/9] oom: do not take callback_mutex David Rientjes
2007-09-20 22:04 ` Christoph Lameter
2007-09-20 22:01 ` [patch 8/9] oom: compare cpuset mems_allowed instead of exclusive ancestors Christoph Lameter
2007-09-20 22:00 ` [patch 7/9] oom: suppress extraneous stack and memory dump Christoph Lameter
2007-09-20 22:03 ` [patch 6/9] oom: add oom_kill_asking_task sysctl Christoph Lameter
2007-09-20 22:07 ` David Rientjes
2007-09-20 22:09 ` Christoph Lameter
2007-09-21 9:05 ` Andrew Morton
2007-09-20 21:59 ` [patch 5/9] oom: serialize out of memory calls Christoph Lameter
2007-09-21 9:01 ` Andrew Morton
2007-09-21 20:04 ` David Rientjes
2007-09-20 21:59 ` [patch 4/9] oom: add per-zone locking Christoph Lameter
2007-09-20 22:03 ` David Rientjes
2007-09-20 22:05 ` Christoph Lameter
2007-09-20 22:12 ` David Rientjes
2007-09-20 22:26 ` Christoph Lameter
2007-09-20 22:48 ` David Rientjes
2007-09-21 8:59 ` Andrew Morton
2007-09-20 21:56 ` [patch 3/9] oom: change all_unreclaimable zone member to flags Christoph Lameter
2007-09-20 21:58 ` David Rientjes
2007-09-21 8:55 ` Andrew Morton
2007-09-21 9:12 ` [patch 0/9] oom killer serialization Andrew Morton
2007-09-21 9:21 ` David Rientjes
2007-09-21 19:13 ` David Rientjes
2007-09-21 19:15 ` Christoph Lameter
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=alpine.DEB.0.9999.0709201321070.25753@chino.kir.corp.google.com \
--to=rientjes@google.com \
--cc=akpm@linux-foundation.org \
--cc=andrea@suse.de \
--cc=clameter@sgi.com \
--cc=linux-mm@kvack.org \
--cc=riel@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox