@@ -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;
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@I-love.SAKURA.ne.jp> --- mm/oom_kill.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-)