linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] mm/oom: Add killed process selection information
@ 2019-08-15  6:06 Edward Chron
  2019-08-15  8:24 ` Michal Hocko
  0 siblings, 1 reply; 11+ messages in thread
From: Edward Chron @ 2019-08-15  6:06 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Michal Hocko, Roman Gushchin, Johannes Weiner, David Rientjes,
	Tetsuo Handa, Shakeel Butt, linux-mm, linux-kernel, colona,
	Edward Chron

For an OOM event: print oom_score_adj value for the OOM Killed process
to document what the oom score adjust value was at the time the process
at the time of the OOM event. The value can be set by the user and it
effects the resulting oom_score so useful to document this value.

Sample message output:
Aug 14 23:00:02 testserver kernel: Out of memory: Killed process 2692
 (oomprocs) total-vm:1056800kB, anon-rss:1052760kB, file-rss:4kB,i
 shmem-rss:0kB oom_score_adj:1000

Signed-off-by: Edward Chron <echron@arista.com>
---
 mm/oom_kill.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index eda2e2a0bdc6..6b1674cac377 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -858,6 +858,7 @@ static void __oom_kill_process(struct task_struct *victim, const char *message)
 	struct task_struct *p;
 	struct mm_struct *mm;
 	bool can_oom_reap = true;
+	long adj;
 
 	p = find_lock_task_mm(victim);
 	if (!p) {
@@ -877,6 +878,8 @@ static void __oom_kill_process(struct task_struct *victim, const char *message)
 	count_vm_event(OOM_KILL);
 	memcg_memory_event_mm(mm, MEMCG_OOM_KILL);
 
+	adj = (long)victim->signal->oom_score_adj;
+
 	/*
 	 * We should send SIGKILL before granting access to memory reserves
 	 * in order to prevent the OOM victim from depleting the memory
@@ -884,12 +887,12 @@ static void __oom_kill_process(struct task_struct *victim, const char *message)
 	 */
 	do_send_sig_info(SIGKILL, SEND_SIG_PRIV, victim, PIDTYPE_TGID);
 	mark_oom_victim(victim);
-	pr_err("%s: Killed process %d (%s) total-vm:%lukB, anon-rss:%lukB, file-rss:%lukB, shmem-rss:%lukB\n",
+	pr_err("%s: Killed process %d (%s) total-vm:%lukB, anon-rss:%lukB, file-rss:%lukB, shmem-rss:%lukB oom_score_adj:%ld\n",
 		message, task_pid_nr(victim), victim->comm,
 		K(victim->mm->total_vm),
 		K(get_mm_counter(victim->mm, MM_ANONPAGES)),
 		K(get_mm_counter(victim->mm, MM_FILEPAGES)),
-		K(get_mm_counter(victim->mm, MM_SHMEMPAGES)));
+		K(get_mm_counter(victim->mm, MM_SHMEMPAGES)), adj);
 	task_unlock(victim);
 
 	/*
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread
* [PATCH] mm/oom: Add killed process selection information
@ 2019-08-08 18:32 Edward Chron
  2019-08-08 18:51 ` Michal Hocko
  0 siblings, 1 reply; 11+ messages in thread
From: Edward Chron @ 2019-08-08 18:32 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Michal Hocko, Roman Gushchin, Johannes Weiner, David Rientjes,
	Tetsuo Handa, Shakeel Butt, linux-mm, linux-kernel, colona,
	Edward Chron

For an OOM event: print oomscore, memory pct, oom adjustment of the process
that OOM kills and the totalpages value in kB (KiB) used in the calculation
with the OOM killed process message. This is helpful to document why the
process was selected by OOM at the time of the OOM event.

Sample message output:
Jul 21 20:07:48 yoursystem kernel: Out of memory: Killed process 2826
 (processname) total-vm:1056800kB, anon-rss:1052784kB, file-rss:4kB,
 shmem-rss:0kB memory-usage:3.2% oom_score:1032 oom_score_adj:1000
 total-pages: 32791748kB

Signed-off-by: Edward Chron <echron@arista.com>
---
 fs/proc/base.c      |  2 +-
 include/linux/oom.h | 18 +++++++++++-
 mm/oom_kill.c       | 67 +++++++++++++++++++++++++++++++++------------
 3 files changed, 68 insertions(+), 19 deletions(-)

diff --git a/fs/proc/base.c b/fs/proc/base.c
index ebea9501afb8..41880990e6a8 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -550,7 +550,7 @@ static int proc_oom_score(struct seq_file *m, struct pid_namespace *ns,
 	unsigned long totalpages = totalram_pages() + total_swap_pages;
 	unsigned long points = 0;
 
-	points = oom_badness(task, totalpages) * 1000 / totalpages;
+	points = oom_badness(task, totalpages, NULL) * 1000 / totalpages;
 	seq_printf(m, "%lu\n", points);
 
 	return 0;
diff --git a/include/linux/oom.h b/include/linux/oom.h
index c696c265f019..7f7ab125c21c 100644
--- a/include/linux/oom.h
+++ b/include/linux/oom.h
@@ -49,6 +49,8 @@ struct oom_control {
 	unsigned long totalpages;
 	struct task_struct *chosen;
 	unsigned long chosen_points;
+	unsigned long chosen_mempts;
+	unsigned long chosen_adj;
 
 	/* Used to print the constraint info. */
 	enum oom_constraint constraint;
@@ -105,10 +107,24 @@ static inline vm_fault_t check_stable_address_space(struct mm_struct *mm)
 	return 0;
 }
 
+/*
+ * Optional argument that can be passed to oom_badness in the arg field
+ *
+ * Input fields that can be filled in: memcg and nodemask
+ * Output fields that can be returned: mempts, adj
+ */
+struct oom_bad_parms {
+	struct mem_cgroup *memcg;
+	const nodemask_t *nodemask;
+	unsigned long mempts;
+	long adj;
+};
+
 bool __oom_reap_task_mm(struct mm_struct *mm);
 
 extern unsigned long oom_badness(struct task_struct *p,
-		unsigned long totalpages);
+				 unsigned long totalpages,
+				 struct oom_bad_parms *obp);
 
 extern bool out_of_memory(struct oom_control *oc);
 
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index eda2e2a0bdc6..0548845dbef8 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -42,6 +42,7 @@
 #include <linux/kthread.h>
 #include <linux/init.h>
 #include <linux/mmu_notifier.h>
+#include <linux/oom.h>
 
 #include <asm/tlb.h>
 #include "internal.h"
@@ -195,7 +196,8 @@ static bool is_dump_unreclaim_slabs(void)
  * predictable as possible.  The goal is to return the highest value for the
  * task consuming the most memory to avoid subsequent oom failures.
  */
-unsigned long oom_badness(struct task_struct *p, unsigned long totalpages)
+unsigned long oom_badness(struct task_struct *p, unsigned long totalpages,
+			  struct oom_bad_parms *obp)
 {
 	long points;
 	long adj;
@@ -208,15 +210,16 @@ unsigned long oom_badness(struct task_struct *p, unsigned long totalpages)
 		return 0;
 
 	/*
-	 * Do not even consider tasks which are explicitly marked oom
-	 * unkillable or have been already oom reaped or the are in
-	 * the middle of vfork
+	 * Do not consider tasks which have already been oom reaped or
+	 * that are in the middle of vfork.
 	 */
 	adj = (long)p->signal->oom_score_adj;
-	if (adj == OOM_SCORE_ADJ_MIN ||
-			test_bit(MMF_OOM_SKIP, &p->mm->flags) ||
-			in_vfork(p)) {
+	if (test_bit(MMF_OOM_SKIP, &p->mm->flags) || in_vfork(p)) {
 		task_unlock(p);
+		if (obp != NULL) {
+			obp->mempts = 0;
+			obp->adj = adj;
+		}
 		return 0;
 	}
 
@@ -228,6 +231,16 @@ unsigned long oom_badness(struct task_struct *p, unsigned long totalpages)
 		mm_pgtables_bytes(p->mm) / PAGE_SIZE;
 	task_unlock(p);
 
+	/* Also return raw mempts and oom_score_adj along */
+	if (obp != NULL) {
+		obp->mempts = points;
+		obp->adj = adj;
+	}
+
+	/* Unkillable oom task skipped but returns mempts and oom_score_adj */
+	if (adj == OOM_SCORE_ADJ_MIN)
+		return 0;
+
 	/* Normalize to oom_score_adj units */
 	adj *= totalpages / 1000;
 	points += adj;
@@ -310,6 +323,8 @@ static int oom_evaluate_task(struct task_struct *task, void *arg)
 {
 	struct oom_control *oc = arg;
 	unsigned long points;
+	struct oom_bad_parms obp = { .memcg = NULL, .nodemask = oc->nodemask,
+				     .mempts = 0, .adj = 0 };
 
 	if (oom_unkillable_task(task))
 		goto next;
@@ -339,7 +354,7 @@ static int oom_evaluate_task(struct task_struct *task, void *arg)
 		goto select;
 	}
 
-	points = oom_badness(task, oc->totalpages);
+	points = oom_badness(task, oc->totalpages, &obp);
 	if (!points || points < oc->chosen_points)
 		goto next;
 
@@ -349,6 +364,8 @@ static int oom_evaluate_task(struct task_struct *task, void *arg)
 	get_task_struct(task);
 	oc->chosen = task;
 	oc->chosen_points = points;
+	oc->chosen_mempts = obp.mempts;
+	oc->chosen_adj = obp.adj;
 next:
 	return 0;
 abort:
@@ -375,6 +392,9 @@ static void select_bad_process(struct oom_control *oc)
 				break;
 		rcu_read_unlock();
 	}
+
+	oc->chosen_points = oc->chosen_points * 1000 / oc->totalpages;
+	oc->chosen_mempts = oc->chosen_mempts * 1000 / oc->totalpages;
 }
 
 static int dump_task(struct task_struct *p, void *arg)
@@ -853,7 +873,8 @@ static bool task_will_free_mem(struct task_struct *task)
 	return ret;
 }
 
-static void __oom_kill_process(struct task_struct *victim, const char *message)
+static void __oom_kill_process(struct task_struct *victim, const char *message,
+				struct oom_control *oc)
 {
 	struct task_struct *p;
 	struct mm_struct *mm;
@@ -884,12 +905,24 @@ static void __oom_kill_process(struct task_struct *victim, const char *message)
 	 */
 	do_send_sig_info(SIGKILL, SEND_SIG_PRIV, victim, PIDTYPE_TGID);
 	mark_oom_victim(victim);
-	pr_err("%s: Killed process %d (%s) total-vm:%lukB, anon-rss:%lukB, file-rss:%lukB, shmem-rss:%lukB\n",
-		message, task_pid_nr(victim), victim->comm,
-		K(victim->mm->total_vm),
-		K(get_mm_counter(victim->mm, MM_ANONPAGES)),
-		K(get_mm_counter(victim->mm, MM_FILEPAGES)),
-		K(get_mm_counter(victim->mm, MM_SHMEMPAGES)));
+
+	if (oc != NULL && oc->chosen_mempts > 0)
+		pr_info("%s: Killed process %d (%s) total-vm:%lukB, anon-rss:%lukB, file-rss:%lukB, shmem-rss:%lukB, memory-usage:%lu.%1lu%% oom_score:%lu oom_score_adj:%ld total-pages: %lukB",
+			message, task_pid_nr(victim), victim->comm,
+			K(victim->mm->total_vm),
+			K(get_mm_counter(victim->mm, MM_ANONPAGES)),
+			K(get_mm_counter(victim->mm, MM_FILEPAGES)),
+			K(get_mm_counter(victim->mm, MM_SHMEMPAGES)),
+			oc->chosen_mempts / 10, oc->chosen_mempts % 10,
+			oc->chosen_points, oc->chosen_adj, K(oc->totalpages));
+	else
+		pr_info("%s: Killed process %d (%s) total-vm:%lukB, anon-rss:%lukB, file-rss:%lukB, shmem-rss:%lukB",
+			message, task_pid_nr(victim), victim->comm,
+			K(victim->mm->total_vm),
+			K(get_mm_counter(victim->mm, MM_ANONPAGES)),
+			K(get_mm_counter(victim->mm, MM_FILEPAGES)),
+			K(get_mm_counter(victim->mm, MM_SHMEMPAGES)));
+
 	task_unlock(victim);
 
 	/*
@@ -942,7 +975,7 @@ static int oom_kill_memcg_member(struct task_struct *task, void *message)
 	if (task->signal->oom_score_adj != OOM_SCORE_ADJ_MIN &&
 	    !is_global_init(task)) {
 		get_task_struct(task);
-		__oom_kill_process(task, message);
+		__oom_kill_process(task, message, NULL);
 	}
 	return 0;
 }
@@ -979,7 +1012,7 @@ static void oom_kill_process(struct oom_control *oc, const char *message)
 	 */
 	oom_group = mem_cgroup_get_oom_group(victim, oc->memcg);
 
-	__oom_kill_process(victim, message);
+	__oom_kill_process(victim, message, oc);
 
 	/*
 	 * If necessary, kill all tasks in the selected memory cgroup.
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2019-08-15  8:24 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-15  6:06 [PATCH] mm/oom: Add killed process selection information Edward Chron
2019-08-15  8:24 ` Michal Hocko
  -- strict thread matches above, loose matches on Subject: below --
2019-08-08 18:32 Edward Chron
2019-08-08 18:51 ` Michal Hocko
     [not found]   ` <CAM3twVT0_f++p1jkvGuyMYtaYtzgEiaUtb8aYNCmNScirE4=og@mail.gmail.com>
2019-08-08 20:07     ` Michal Hocko
2019-08-08 22:15       ` Edward Chron
2019-08-09  6:40         ` Michal Hocko
2019-08-09 22:15           ` Edward Chron
2019-08-12 11:42             ` Michal Hocko
2019-08-15  6:24               ` Edward Chron
2019-08-15  8:18                 ` Michal Hocko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).