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 | ||
