Since "mm, oom: Avoid potential RCU stall at dump_tasks()." changed to cache all candidates at select_bad_process(), dump_tasks() started printing all threads upon memcg OOM event. Unfortunately, mem_cgroup_scan_tasks() can't traverse on only thread group leaders because CSS_TASK_ITER_PROCS does not work if the thread group leader already exit()ed. Signed-off-by: Tetsuo Handa <penguin-kernel@xxxxxxxxxxxxxxxxxxx> --- mm/oom_kill.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/mm/oom_kill.c b/mm/oom_kill.c index bdd90b53bbd3..a92b2f70d15b 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -334,6 +334,20 @@ static int oom_evaluate_task(struct task_struct *task, void *arg) goto abort; } + /* + * Since mem_cgroup_scan_tasks() calls this function on each thread + * whlie for_each_process() calls this function on each thread group, + * memcg OOM should evaluate only one thread from each thread group. + */ + if (is_memcg_oom(oc) && get_nr_threads(task) != 1) { + struct task_struct *p; + + list_for_each_entry_reverse(p, &oom_candidate_list, + oom_candidate_list) + if (same_thread_group(p, task)) + goto next; + } + get_task_struct(task); list_add_tail(&task->oom_candidate_list, &oom_candidate_list); @@ -350,9 +364,6 @@ static int oom_evaluate_task(struct task_struct *task, void *arg) if (!points || points < oc->chosen_points) goto next; - /* Prefer thread group leaders for display purposes */ - if (points == oc->chosen_points && thread_group_leader(oc->chosen)) - goto next; select: oc->chosen = task; oc->chosen_points = points; -- 2.16.5