aboutsummaryrefslogtreecommitdiffstats
path: root/mm/oom_kill.c
diff options
context:
space:
mode:
authorKOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>2010-08-09 17:18:46 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-09 20:44:56 -0700
commitc55db95788a2a55a77f5a3ced1e59578710440b2 (patch)
tree275a0c97bfe408ea926dfe14864e476d719859e9 /mm/oom_kill.c
parentoom: introduce find_lock_task_mm() to fix !mm false positives (diff)
downloadlinux-dev-c55db95788a2a55a77f5a3ced1e59578710440b2.tar.xz
linux-dev-c55db95788a2a55a77f5a3ced1e59578710440b2.zip
oom: dump_tasks use find_lock_task_mm too
dump_task() should use find_lock_task_mm() too. It is necessary for protecting task-exiting race. dump_tasks() currently filters any task that does not have an attached ->mm since it incorrectly assumes that it must either be in the process of exiting and has detached its memory or that it's a kernel thread; multithreaded tasks may actually have subthreads that have a valid ->mm pointer and thus those threads should actually be displayed. This change finds those threads, if they exist, and emit their information along with the rest of the candidate tasks for kill. Signed-off-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Signed-off-by: David Rientjes <rientjes@google.com> Cc: Balbir Singh <balbir@in.ibm.com> Cc: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/oom_kill.c')
-rw-r--r--mm/oom_kill.c39
1 files changed, 21 insertions, 18 deletions
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 9a686aa35a48..5285da9a9c1a 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -336,35 +336,38 @@ static struct task_struct *select_bad_process(unsigned long *ppoints,
*/
static void dump_tasks(const struct mem_cgroup *mem)
{
- struct task_struct *g, *p;
+ struct task_struct *p;
+ struct task_struct *task;
printk(KERN_INFO "[ pid ] uid tgid total_vm rss cpu oom_adj "
"name\n");
- do_each_thread(g, p) {
- struct mm_struct *mm;
-
- if (mem && !task_in_mem_cgroup(p, mem))
+ for_each_process(p) {
+ /*
+ * We don't have is_global_init() check here, because the old
+ * code do that. printing init process is not big matter. But
+ * we don't hope to make unnecessary compatibility breaking.
+ */
+ if (p->flags & PF_KTHREAD)
continue;
- if (!thread_group_leader(p))
+ if (mem && !task_in_mem_cgroup(p, mem))
continue;
- task_lock(p);
- mm = p->mm;
- if (!mm) {
+ task = find_lock_task_mm(p);
+ if (!task) {
/*
- * total_vm and rss sizes do not exist for tasks with no
- * mm so there's no need to report them; they can't be
- * oom killed anyway.
+ * Probably oom vs task-exiting race was happen and ->mm
+ * have been detached. thus there's no need to report
+ * them; they can't be oom killed anyway.
*/
- task_unlock(p);
continue;
}
+
printk(KERN_INFO "[%5d] %5d %5d %8lu %8lu %3d %3d %s\n",
- p->pid, __task_cred(p)->uid, p->tgid, mm->total_vm,
- get_mm_rss(mm), (int)task_cpu(p), p->signal->oom_adj,
- p->comm);
- task_unlock(p);
- } while_each_thread(g, p);
+ task->pid, __task_cred(task)->uid, task->tgid,
+ task->mm->total_vm, get_mm_rss(task->mm),
+ (int)task_cpu(task), task->signal->oom_adj, p->comm);
+ task_unlock(task);
+ }
}
static void dump_header(struct task_struct *p, gfp_t gfp_mask, int order,