On Wed, 17 Jul 2019 19:55:01 +0900 Tetsuo Handa <penguin-kernel@xxxxxxxxxxxxxxxxxxx> wrote: > Currently dump_tasks() might call printk() for many thousands times under > RCU, which might take many minutes for slow consoles. Therefore, split > dump_tasks() into three stages; take a snapshot of possible OOM victim > candidates under RCU, dump the snapshot from reschedulable context, and > destroy the snapshot. > > In a future patch, the first stage would be moved to select_bad_process() > and the third stage would be moved to after oom_kill_process(), and will > simplify refcount handling. Look straightforward enough. > > ... > > static void dump_tasks(struct oom_control *oc) > { > - pr_info("Tasks state (memory values in pages):\n"); > - pr_info("[ pid ] uid tgid total_vm rss pgtables_bytes swapents oom_score_adj name\n"); > + static LIST_HEAD(list); I don't think this needs to be static? > + struct task_struct *p; > + struct task_struct *t; > > if (is_memcg_oom(oc)) > - mem_cgroup_scan_tasks(oc->memcg, dump_task, oc); > + mem_cgroup_scan_tasks(oc->memcg, add_candidate_task, &list); > else { > - struct task_struct *p; > - > rcu_read_lock(); > for_each_process(p) > - dump_task(p, oc); > + add_candidate_task(p, &list); > rcu_read_unlock(); > } > + pr_info("Tasks state (memory values in pages):\n"); > + pr_info("[ pid ] uid tgid total_vm rss pgtables_bytes swapents oom_score_adj name\n"); > + list_for_each_entry(p, &list, oom_victim_list) { > + cond_resched(); > + /* p may not have freeable memory in nodemask */ > + if (!is_memcg_oom(oc) && !oom_cpuset_eligible(p, oc)) > + continue; > + /* All of p's threads might have already detached their mm's. */ > + t = find_lock_task_mm(p); > + if (!t) > + continue; > + pr_info("[%7d] %5d %5d %8lu %8lu %8ld %8lu %5hd %s\n", > + t->pid, from_kuid(&init_user_ns, task_uid(t)), > + t->tgid, t->mm->total_vm, get_mm_rss(t->mm), > + mm_pgtables_bytes(t->mm), > + get_mm_counter(t->mm, MM_SWAPENTS), > + t->signal->oom_score_adj, t->comm); > + task_unlock(t); > + } > + list_for_each_entry_safe(p, t, &list, oom_victim_list) { > + list_del(&p->oom_victim_list); > + put_task_struct(p); > + } > }