diff options
author | Pavel Emelianov <xemul@openvz.org> | 2008-02-07 00:13:58 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-07 08:42:19 -0800 |
commit | c7ba5c9e8176704bfac0729875fa62798037584d (patch) | |
tree | 00df1c4cb67e313cdb66233381b4cee275fd46c0 | |
parent | 0eea10301708c64a6b793894c156e21ddd15eb64 (diff) |
Memory controller: OOM handling
Out of memory handling for cgroups over their limit. A task from the
cgroup over limit is chosen using the existing OOM logic and killed.
TODO:
1. As discussed in the OLS BOF session, consider implementing a user
space policy for OOM handling.
[akpm@linux-foundation.org: fix build due to oom-killer changes]
Signed-off-by: Pavel Emelianov <xemul@openvz.org>
Signed-off-by: Balbir Singh <balbir@linux.vnet.ibm.com>
Cc: Paul Menage <menage@google.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: Nick Piggin <nickpiggin@yahoo.com.au>
Cc: Kirill Korotaev <dev@sw.ru>
Cc: Herbert Poetzl <herbert@13thfloor.at>
Cc: David Rientjes <rientjes@google.com>
Cc: Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | include/linux/memcontrol.h | 1 | ||||
-rw-r--r-- | mm/memcontrol.c | 1 | ||||
-rw-r--r-- | mm/oom_kill.c | 43 |
3 files changed, 41 insertions, 4 deletions
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 9c3c1c97c19..9bbbf524ba8 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -39,6 +39,7 @@ extern unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan, int mode, struct zone *z, struct mem_cgroup *mem_cont, int active); +extern void mem_cgroup_out_of_memory(struct mem_cgroup *mem, gfp_t gfp_mask); static inline void mem_cgroup_uncharge_page(struct page *page) { diff --git a/mm/memcontrol.c b/mm/memcontrol.c index d73692279ab..5260658c90a 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -329,6 +329,7 @@ retry: } css_put(&mem->css); + mem_cgroup_out_of_memory(mem, GFP_KERNEL); goto free_pc; } diff --git a/mm/oom_kill.c b/mm/oom_kill.c index c1850bf991c..64751dc9d99 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -25,6 +25,7 @@ #include <linux/cpuset.h> #include <linux/module.h> #include <linux/notifier.h> +#include <linux/memcontrol.h> int sysctl_panic_on_oom; int sysctl_oom_kill_allocating_task; @@ -50,7 +51,8 @@ static DEFINE_SPINLOCK(zone_scan_mutex); * of least surprise ... (be careful when you change it) */ -unsigned long badness(struct task_struct *p, unsigned long uptime) +unsigned long badness(struct task_struct *p, unsigned long uptime, + struct mem_cgroup *mem) { unsigned long points, cpu_time, run_time, s; struct mm_struct *mm; @@ -63,6 +65,13 @@ unsigned long badness(struct task_struct *p, unsigned long uptime) return 0; } +#ifdef CONFIG_CGROUP_MEM_CONT + if (mem != NULL && mm->mem_cgroup != mem) { + task_unlock(p); + return 0; + } +#endif + /* * The memory size of the process is the basis for the badness. */ @@ -193,7 +202,8 @@ static inline enum oom_constraint constrained_alloc(struct zonelist *zonelist, * * (not docbooked, we don't want this one cluttering up the manual) */ -static struct task_struct *select_bad_process(unsigned long *ppoints) +static struct task_struct *select_bad_process(unsigned long *ppoints, + struct mem_cgroup *mem) { struct task_struct *g, *p; struct task_struct *chosen = NULL; @@ -247,7 +257,7 @@ static struct task_struct *select_bad_process(unsigned long *ppoints) if (p->oomkilladj == OOM_DISABLE) continue; - points = badness(p, uptime.tv_sec); + points = badness(p, uptime.tv_sec, mem); if (points > *ppoints || !chosen) { chosen = p; *ppoints = points; @@ -368,6 +378,31 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order, return oom_kill_task(p); } +#ifdef CONFIG_CGROUP_MEM_CONT +void mem_cgroup_out_of_memory(struct mem_cgroup *mem, gfp_t gfp_mask) +{ + unsigned long points = 0; + struct task_struct *p; + + cgroup_lock(); + rcu_read_lock(); +retry: + p = select_bad_process(&points, mem); + if (PTR_ERR(p) == -1UL) + goto out; + + if (!p) + p = current; + + if (oom_kill_process(p, gfp_mask, 0, points, + "Memory cgroup out of memory")) + goto retry; +out: + rcu_read_unlock(); + cgroup_unlock(); +} +#endif + static BLOCKING_NOTIFIER_HEAD(oom_notify_list); int register_oom_notifier(struct notifier_block *nb) @@ -484,7 +519,7 @@ retry: * Rambo mode: Shoot down a process and hope it solves whatever * issues we may have. */ - p = select_bad_process(&points); + p = select_bad_process(&points, NULL); if (PTR_ERR(p) == -1UL) goto out; |