diff options
author | KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> | 2010-08-10 21:03:00 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-11 11:59:19 -0400 |
commit | 158e0a2d1b3cffed8b46cbc56393a1394672ef79 (patch) | |
tree | a044d53137609fdfc8c1afdde366b3e205c96eda | |
parent | 73045c47b6facbdf4656e6763c8cb469de4337e2 (diff) |
memcg: use find_lock_task_mm() in memory cgroups oom
When the OOM killer scans task, it check a task is under memcg or
not when it's called via memcg's context.
But, as Oleg pointed out, a thread group leader may have NULL ->mm
and task_in_mem_cgroup() may do wrong decision. We have to use
find_lock_task_mm() in memcg as generic OOM-Killer does.
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
Cc: Balbir Singh <balbir@linux.vnet.ibm.com>
Reviewed-by: Minchan Kim <minchan.kim@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | include/linux/oom.h | 2 | ||||
-rw-r--r-- | mm/memcontrol.c | 10 | ||||
-rw-r--r-- | mm/oom_kill.c | 2 |
3 files changed, 10 insertions, 4 deletions
diff --git a/include/linux/oom.h b/include/linux/oom.h index f209b683e118..5e3aa8311c5e 100644 --- a/include/linux/oom.h +++ b/include/linux/oom.h | |||
@@ -66,6 +66,8 @@ static inline void oom_killer_enable(void) | |||
66 | extern unsigned long badness(struct task_struct *p, struct mem_cgroup *mem, | 66 | extern unsigned long badness(struct task_struct *p, struct mem_cgroup *mem, |
67 | const nodemask_t *nodemask, unsigned long uptime); | 67 | const nodemask_t *nodemask, unsigned long uptime); |
68 | 68 | ||
69 | extern struct task_struct *find_lock_task_mm(struct task_struct *p); | ||
70 | |||
69 | /* sysctls */ | 71 | /* sysctls */ |
70 | extern int sysctl_oom_dump_tasks; | 72 | extern int sysctl_oom_dump_tasks; |
71 | extern int sysctl_oom_kill_allocating_task; | 73 | extern int sysctl_oom_kill_allocating_task; |
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index ea5f5edf00b7..f52b0a1861c4 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <linux/mm_inline.h> | 47 | #include <linux/mm_inline.h> |
48 | #include <linux/page_cgroup.h> | 48 | #include <linux/page_cgroup.h> |
49 | #include <linux/cpu.h> | 49 | #include <linux/cpu.h> |
50 | #include <linux/oom.h> | ||
50 | #include "internal.h" | 51 | #include "internal.h" |
51 | 52 | ||
52 | #include <asm/uaccess.h> | 53 | #include <asm/uaccess.h> |
@@ -838,10 +839,13 @@ int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *mem) | |||
838 | { | 839 | { |
839 | int ret; | 840 | int ret; |
840 | struct mem_cgroup *curr = NULL; | 841 | struct mem_cgroup *curr = NULL; |
842 | struct task_struct *p; | ||
841 | 843 | ||
842 | task_lock(task); | 844 | p = find_lock_task_mm(task); |
843 | curr = try_get_mem_cgroup_from_mm(task->mm); | 845 | if (!p) |
844 | task_unlock(task); | 846 | return 0; |
847 | curr = try_get_mem_cgroup_from_mm(p->mm); | ||
848 | task_unlock(p); | ||
845 | if (!curr) | 849 | if (!curr) |
846 | return 0; | 850 | return 0; |
847 | /* | 851 | /* |
diff --git a/mm/oom_kill.c b/mm/oom_kill.c index d3def05a33d9..5014e50644d1 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c | |||
@@ -106,7 +106,7 @@ static void boost_dying_task_prio(struct task_struct *p, | |||
106 | * pointer. Return p, or any of its subthreads with a valid ->mm, with | 106 | * pointer. Return p, or any of its subthreads with a valid ->mm, with |
107 | * task_lock() held. | 107 | * task_lock() held. |
108 | */ | 108 | */ |
109 | static struct task_struct *find_lock_task_mm(struct task_struct *p) | 109 | struct task_struct *find_lock_task_mm(struct task_struct *p) |
110 | { | 110 | { |
111 | struct task_struct *t = p; | 111 | struct task_struct *t = p; |
112 | 112 | ||