aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Emelianov <xemul@openvz.org>2008-02-07 03:13:58 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-07 11:42:19 -0500
commitc7ba5c9e8176704bfac0729875fa62798037584d (patch)
tree00df1c4cb67e313cdb66233381b4cee275fd46c0
parent0eea10301708c64a6b793894c156e21ddd15eb64 (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.h1
-rw-r--r--mm/memcontrol.c1
-rw-r--r--mm/oom_kill.c43
3 files changed, 41 insertions, 4 deletions
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 9c3c1c97c197..9bbbf524ba8f 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,
39 int mode, struct zone *z, 39 int mode, struct zone *z,
40 struct mem_cgroup *mem_cont, 40 struct mem_cgroup *mem_cont,
41 int active); 41 int active);
42extern void mem_cgroup_out_of_memory(struct mem_cgroup *mem, gfp_t gfp_mask);
42 43
43static inline void mem_cgroup_uncharge_page(struct page *page) 44static inline void mem_cgroup_uncharge_page(struct page *page)
44{ 45{
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index d73692279ab1..5260658c90aa 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -329,6 +329,7 @@ retry:
329 } 329 }
330 330
331 css_put(&mem->css); 331 css_put(&mem->css);
332 mem_cgroup_out_of_memory(mem, GFP_KERNEL);
332 goto free_pc; 333 goto free_pc;
333 } 334 }
334 335
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index c1850bf991cd..64751dc9d997 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -25,6 +25,7 @@
25#include <linux/cpuset.h> 25#include <linux/cpuset.h>
26#include <linux/module.h> 26#include <linux/module.h>
27#include <linux/notifier.h> 27#include <linux/notifier.h>
28#include <linux/memcontrol.h>
28 29
29int sysctl_panic_on_oom; 30int sysctl_panic_on_oom;
30int sysctl_oom_kill_allocating_task; 31int sysctl_oom_kill_allocating_task;
@@ -50,7 +51,8 @@ static DEFINE_SPINLOCK(zone_scan_mutex);
50 * of least surprise ... (be careful when you change it) 51 * of least surprise ... (be careful when you change it)
51 */ 52 */
52 53
53unsigned long badness(struct task_struct *p, unsigned long uptime) 54unsigned long badness(struct task_struct *p, unsigned long uptime,
55 struct mem_cgroup *mem)
54{ 56{
55 unsigned long points, cpu_time, run_time, s; 57 unsigned long points, cpu_time, run_time, s;
56 struct mm_struct *mm; 58 struct mm_struct *mm;
@@ -63,6 +65,13 @@ unsigned long badness(struct task_struct *p, unsigned long uptime)
63 return 0; 65 return 0;
64 } 66 }
65 67
68#ifdef CONFIG_CGROUP_MEM_CONT
69 if (mem != NULL && mm->mem_cgroup != mem) {
70 task_unlock(p);
71 return 0;
72 }
73#endif
74
66 /* 75 /*
67 * The memory size of the process is the basis for the badness. 76 * The memory size of the process is the basis for the badness.
68 */ 77 */
@@ -193,7 +202,8 @@ static inline enum oom_constraint constrained_alloc(struct zonelist *zonelist,
193 * 202 *
194 * (not docbooked, we don't want this one cluttering up the manual) 203 * (not docbooked, we don't want this one cluttering up the manual)
195 */ 204 */
196static struct task_struct *select_bad_process(unsigned long *ppoints) 205static struct task_struct *select_bad_process(unsigned long *ppoints,
206 struct mem_cgroup *mem)
197{ 207{
198 struct task_struct *g, *p; 208 struct task_struct *g, *p;
199 struct task_struct *chosen = NULL; 209 struct task_struct *chosen = NULL;
@@ -247,7 +257,7 @@ static struct task_struct *select_bad_process(unsigned long *ppoints)
247 if (p->oomkilladj == OOM_DISABLE) 257 if (p->oomkilladj == OOM_DISABLE)
248 continue; 258 continue;
249 259
250 points = badness(p, uptime.tv_sec); 260 points = badness(p, uptime.tv_sec, mem);
251 if (points > *ppoints || !chosen) { 261 if (points > *ppoints || !chosen) {
252 chosen = p; 262 chosen = p;
253 *ppoints = points; 263 *ppoints = points;
@@ -368,6 +378,31 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
368 return oom_kill_task(p); 378 return oom_kill_task(p);
369} 379}
370 380
381#ifdef CONFIG_CGROUP_MEM_CONT
382void mem_cgroup_out_of_memory(struct mem_cgroup *mem, gfp_t gfp_mask)
383{
384 unsigned long points = 0;
385 struct task_struct *p;
386
387 cgroup_lock();
388 rcu_read_lock();
389retry:
390 p = select_bad_process(&points, mem);
391 if (PTR_ERR(p) == -1UL)
392 goto out;
393
394 if (!p)
395 p = current;
396
397 if (oom_kill_process(p, gfp_mask, 0, points,
398 "Memory cgroup out of memory"))
399 goto retry;
400out:
401 rcu_read_unlock();
402 cgroup_unlock();
403}
404#endif
405
371static BLOCKING_NOTIFIER_HEAD(oom_notify_list); 406static BLOCKING_NOTIFIER_HEAD(oom_notify_list);
372 407
373int register_oom_notifier(struct notifier_block *nb) 408int register_oom_notifier(struct notifier_block *nb)
@@ -484,7 +519,7 @@ retry:
484 * Rambo mode: Shoot down a process and hope it solves whatever 519 * Rambo mode: Shoot down a process and hope it solves whatever
485 * issues we may have. 520 * issues we may have.
486 */ 521 */
487 p = select_bad_process(&points); 522 p = select_bad_process(&points, NULL);
488 523
489 if (PTR_ERR(p) == -1UL) 524 if (PTR_ERR(p) == -1UL)
490 goto out; 525 goto out;