The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [RFC PATCH] mm/oom_kill: dump top 5 memory consumers by RSS in OOM report
@ 2026-08-11  6:29 Ye Liu
  2026-08-13  8:12 ` Michal Hocko
  0 siblings, 1 reply; 3+ messages in thread
From: Ye Liu @ 2026-08-11  6:29 UTC (permalink / raw)
  To: Michal Hocko, Andrew Morton
  Cc: Ye Liu, David Rientjes, Shakeel Butt, linux-mm, linux-kernel

From: Ye Liu <liuye@kylinos.cn>

When the OOM killer triggers, dump_tasks() prints every task's memory
state but in no particular order.  On systems with hundreds of
processes, identifying the heaviest memory consumers requires manual
log post-processing.

Add a top-5 RSS summary at the end of the task dump so operators can
immediately see which processes are consuming the most physical memory
without additional tooling.  The full task list remains unchanged for
backwards compatibility.

The collection reuses the existing dump_task() traversal with zero
additional locking; RSS is read under the same task_lock that
dump_task() already acquires.  The insertion sort over a 5-element
array is O(1) per task and negligible compared to pr_info() overhead.

Signed-off-by: Ye Liu <liuye@kylinos.cn>
---

test:
	stress --cpu 8 --io 4 --vm 2 --vm-bytes 100G
dmesg:
[root@kylinos ~]# dmesg |grep -A 6 "Top 5 memory consumers by RSS"
[   51.670309] Top 5 memory consumers by RSS (pages):
[   51.670312]   #  [  pid  ]   uid      rss  name
[   51.670321]   1  [   7379]     0 13516544  stress
[   51.670328]   2  [   7382]     0 11122123  stress
[   51.670337]   3  [   3861]     0     8158  Xorg
[   51.670344]   4  [   4228]   995     6288  kwin_x11
[   51.670353]   5  [   4272]   995     5903  ukui-screensave
--
[  434.642788] Top 5 memory consumers by RSS (pages):
[  434.642795]   #  [  pid  ]   uid      rss  name
[  434.642802]   1  [   7442]     0 12324420  stress
[  434.642808]   2  [   7445]     0 12318626  stress
[  434.642817]   3  [   3861]     0     4766  Xorg
[  434.642824]   4  [   2693]     0     3963  firewalld
[  434.642832]   5  [   2856]     0     3028  tuned


 mm/oom_kill.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 72 insertions(+), 4 deletions(-)

diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 5f372f6e26fa..36a9863b502c 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -376,10 +376,55 @@ static void select_bad_process(struct oom_control *oc)
 	}
 }
 
+#define OOM_TOP_CONSUMERS	5
+
+struct oom_top_consumer {
+	pid_t		pid;
+	uid_t		uid;
+	unsigned long	rss;
+	char		comm[TASK_COMM_LEN];
+};
+
+struct oom_dump_context {
+	struct oom_control	*oc;
+	struct oom_top_consumer	top[OOM_TOP_CONSUMERS];
+	int			top_count;
+};
+
+static void oom_top_consumer_add(struct oom_top_consumer *top, int *count,
+				 pid_t pid, uid_t uid, unsigned long rss,
+				 const char *comm)
+{
+	int i, pos = *count;
+
+	for (i = 0; i < *count; i++) {
+		if (rss > top[i].rss) {
+			pos = i;
+			break;
+		}
+	}
+
+	if (pos >= OOM_TOP_CONSUMERS)
+		return;
+
+	for (i = min(*count, OOM_TOP_CONSUMERS - 1); i > pos; i--)
+		top[i] = top[i - 1];
+
+	top[pos].pid = pid;
+	top[pos].uid = uid;
+	top[pos].rss = rss;
+	strscpy(top[pos].comm, comm, sizeof(top[pos].comm));
+
+	if (*count < OOM_TOP_CONSUMERS)
+		(*count)++;
+}
+
 static int dump_task(struct task_struct *p, void *arg)
 {
-	struct oom_control *oc = arg;
+	struct oom_dump_context *ctx = arg;
+	struct oom_control *oc = ctx->oc;
 	struct task_struct *task;
+	unsigned long rss;
 
 	if (oom_unkillable_task(p))
 		return 0;
@@ -397,13 +442,18 @@ static int dump_task(struct task_struct *p, void *arg)
 		return 0;
 	}
 
+	rss = get_mm_rss_sum(task->mm);
 	pr_info("[%7d] %5d %5d %8lu %8lu %8lu %8lu %9lu %8ld %8lu         %5hd %s\n",
 		task->pid, from_kuid(&init_user_ns, task_uid(task)),
-		task->tgid, task->mm->total_vm, get_mm_rss_sum(task->mm),
+		task->tgid, task->mm->total_vm, rss,
 		get_mm_counter_sum(task->mm, MM_ANONPAGES), get_mm_counter_sum(task->mm, MM_FILEPAGES),
 		get_mm_counter_sum(task->mm, MM_SHMEMPAGES), mm_pgtables_bytes(task->mm),
 		get_mm_counter_sum(task->mm, MM_SWAPENTS),
 		task->signal->oom_score_adj, task->comm);
+
+	oom_top_consumer_add(ctx->top, &ctx->top_count, task->pid,
+			     from_kuid(&init_user_ns, task_uid(task)),
+			     rss, task->comm);
 	task_unlock(task);
 
 	return 0;
@@ -418,14 +468,20 @@ static int dump_task(struct task_struct *p, void *arg)
  * are not shown.
  * State information includes task's pid, uid, tgid, vm size, rss,
  * pgtables_bytes, swapents, oom_score_adj value, and name.
+ *
+ * After the full task list, a summary of the top OOM_TOP_CONSUMERS memory
+ * consumers by RSS is printed to aid quick diagnosis without manual log
+ * post-processing.
  */
 static void dump_tasks(struct oom_control *oc)
 {
+	struct oom_dump_context ctx = { .oc = oc };
+
 	pr_info("Tasks state (memory values in pages):\n");
 	pr_info("[  pid  ]   uid  tgid total_vm      rss rss_anon rss_file rss_shmem pgtables_bytes swapents oom_score_adj name\n");
 
 	if (is_memcg_oom(oc))
-		mem_cgroup_scan_tasks(oc->memcg, dump_task, oc);
+		mem_cgroup_scan_tasks(oc->memcg, dump_task, &ctx);
 	else {
 		struct task_struct *p;
 		int i = 0;
@@ -435,10 +491,22 @@ static void dump_tasks(struct oom_control *oc)
 			/* Avoid potential softlockup warning */
 			if ((++i & 1023) == 0)
 				touch_softlockup_watchdog();
-			dump_task(p, oc);
+			dump_task(p, &ctx);
 		}
 		rcu_read_unlock();
 	}
+
+	if (ctx.top_count > 0) {
+		int i;
+
+		pr_info("Top %d memory consumers by RSS (pages):\n",
+			ctx.top_count);
+		pr_info("  #  [  pid  ]   uid      rss  name\n");
+		for (i = 0; i < ctx.top_count; i++)
+			pr_info("  %d  [%7d] %5d %8lu  %s\n",
+				i + 1, ctx.top[i].pid, ctx.top[i].uid,
+				ctx.top[i].rss, ctx.top[i].comm);
+	}
 }
 
 static void dump_oom_victim(struct oom_control *oc, struct task_struct *victim)
-- 
2.25.1


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

* Re: [RFC PATCH] mm/oom_kill: dump top 5 memory consumers by RSS in OOM report
  2026-08-11  6:29 [RFC PATCH] mm/oom_kill: dump top 5 memory consumers by RSS in OOM report Ye Liu
@ 2026-08-13  8:12 ` Michal Hocko
  2026-08-13  9:48   ` Ye Liu
  0 siblings, 1 reply; 3+ messages in thread
From: Michal Hocko @ 2026-08-13  8:12 UTC (permalink / raw)
  To: Ye Liu
  Cc: Andrew Morton, Ye Liu, David Rientjes, Shakeel Butt, linux-mm,
	linux-kernel

On Tue 11-08-26 14:29:24, Ye Liu wrote:
> From: Ye Liu <liuye@kylinos.cn>
> 
> When the OOM killer triggers, dump_tasks() prints every task's memory
> state but in no particular order.  On systems with hundreds of
> processes, identifying the heaviest memory consumers requires manual
> log post-processing.

Yes, but why is that a problem? It should be a pretty easy script, no?
-- 
Michal Hocko
SUSE Labs

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

* Re: [RFC PATCH] mm/oom_kill: dump top 5 memory consumers by RSS in OOM report
  2026-08-13  8:12 ` Michal Hocko
@ 2026-08-13  9:48   ` Ye Liu
  0 siblings, 0 replies; 3+ messages in thread
From: Ye Liu @ 2026-08-13  9:48 UTC (permalink / raw)
  To: Michal Hocko
  Cc: Andrew Morton, Ye Liu, David Rientjes, Shakeel Butt, linux-mm,
	linux-kernel



在 2026/8/13 16:12, Michal Hocko 写道:
> On Tue 11-08-26 14:29:24, Ye Liu wrote:
>> From: Ye Liu <liuye@kylinos.cn>
>>
>> When the OOM killer triggers, dump_tasks() prints every task's memory
>> state but in no particular order.  On systems with hundreds of
>> processes, identifying the heaviest memory consumers requires manual
>> log post-processing.
> 
> Yes, but why is that a problem? It should be a pretty easy script, no?

I think I've realized that problems that can be solved in user space 
shouldn't burden the kernel. Thank you.

-- 
Thanks,
Ye Liu


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

end of thread, other threads:[~2026-08-13  9:48 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-11  6:29 [RFC PATCH] mm/oom_kill: dump top 5 memory consumers by RSS in OOM report Ye Liu
2026-08-13  8:12 ` Michal Hocko
2026-08-13  9:48   ` Ye Liu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox