mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-07-08 18:13:59 +02:00
2ea4658783
[ Upstream commit72ba14deb4] The current implementation of the mark_victim tracepoint provides only the process ID (pid) of the victim process. This limitation poses challenges for userspace tools requiring real-time OOM analysis and intervention. Although this information is available from the kernel logs, it’s not the appropriate format to provide OOM notifications. In Android, BPF programs are used with the mark_victim trace events to notify userspace of an OOM kill. For consistency, update the trace event to include the same information about the OOMed victim as the kernel logs. - UID In Android each installed application has a unique UID. Including the `uid` assists in correlating OOM events with specific apps. - Process Name (comm) Enables identification of the affected process. - OOM Score Will allow userspace to get additional insight of the relative kill priority of the OOM victim. In Android, the oom_score_adj is used to categorize app state (foreground, background, etc.), which aids in analyzing user-perceptible impacts of OOM events [1]. - Total VM, RSS Stats, and pgtables Amount of memory used by the victim that will, potentially, be freed up by killing it. [1] https://cs.android.com/android/platform/superproject/main/+/246dc8fc95b6d93afcba5c6d6c133307abb3ac2e:frameworks/base/services/core/java/com/android/server/am/ProcessList.java;l=188-283 Signed-off-by: Carlos Galo <carlosgalo@google.com> Reviewed-by: Steven Rostedt <rostedt@goodmis.org> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Michal Hocko <mhocko@suse.com> Cc: "Masami Hiramatsu (Google)" <mhiramat@kernel.org> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Stable-dep-of:ade81479c7("memcg: fix soft lockup in the OOM process") Signed-off-by: Sasha Levin <sashal@kernel.org>
224 lines
5.0 KiB
C
224 lines
5.0 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#undef TRACE_SYSTEM
|
|
#define TRACE_SYSTEM oom
|
|
|
|
#if !defined(_TRACE_OOM_H) || defined(TRACE_HEADER_MULTI_READ)
|
|
#define _TRACE_OOM_H
|
|
#include <linux/tracepoint.h>
|
|
#include <trace/events/mmflags.h>
|
|
|
|
#define PG_COUNT_TO_KB(x) ((x) << (PAGE_SHIFT - 10))
|
|
|
|
TRACE_EVENT(oom_score_adj_update,
|
|
|
|
TP_PROTO(struct task_struct *task),
|
|
|
|
TP_ARGS(task),
|
|
|
|
TP_STRUCT__entry(
|
|
__field( pid_t, pid)
|
|
__array( char, comm, TASK_COMM_LEN )
|
|
__field( short, oom_score_adj)
|
|
),
|
|
|
|
TP_fast_assign(
|
|
__entry->pid = task->pid;
|
|
memcpy(__entry->comm, task->comm, TASK_COMM_LEN);
|
|
__entry->oom_score_adj = task->signal->oom_score_adj;
|
|
),
|
|
|
|
TP_printk("pid=%d comm=%s oom_score_adj=%hd",
|
|
__entry->pid, __entry->comm, __entry->oom_score_adj)
|
|
);
|
|
|
|
TRACE_EVENT(reclaim_retry_zone,
|
|
|
|
TP_PROTO(struct zoneref *zoneref,
|
|
int order,
|
|
unsigned long reclaimable,
|
|
unsigned long available,
|
|
unsigned long min_wmark,
|
|
int no_progress_loops,
|
|
bool wmark_check),
|
|
|
|
TP_ARGS(zoneref, order, reclaimable, available, min_wmark, no_progress_loops, wmark_check),
|
|
|
|
TP_STRUCT__entry(
|
|
__field( int, node)
|
|
__field( int, zone_idx)
|
|
__field( int, order)
|
|
__field( unsigned long, reclaimable)
|
|
__field( unsigned long, available)
|
|
__field( unsigned long, min_wmark)
|
|
__field( int, no_progress_loops)
|
|
__field( bool, wmark_check)
|
|
),
|
|
|
|
TP_fast_assign(
|
|
__entry->node = zone_to_nid(zoneref->zone);
|
|
__entry->zone_idx = zoneref->zone_idx;
|
|
__entry->order = order;
|
|
__entry->reclaimable = reclaimable;
|
|
__entry->available = available;
|
|
__entry->min_wmark = min_wmark;
|
|
__entry->no_progress_loops = no_progress_loops;
|
|
__entry->wmark_check = wmark_check;
|
|
),
|
|
|
|
TP_printk("node=%d zone=%-8s order=%d reclaimable=%lu available=%lu min_wmark=%lu no_progress_loops=%d wmark_check=%d",
|
|
__entry->node, __print_symbolic(__entry->zone_idx, ZONE_TYPE),
|
|
__entry->order,
|
|
__entry->reclaimable, __entry->available, __entry->min_wmark,
|
|
__entry->no_progress_loops,
|
|
__entry->wmark_check)
|
|
);
|
|
|
|
TRACE_EVENT(mark_victim,
|
|
TP_PROTO(struct task_struct *task, uid_t uid),
|
|
|
|
TP_ARGS(task, uid),
|
|
|
|
TP_STRUCT__entry(
|
|
__field(int, pid)
|
|
__string(comm, task->comm)
|
|
__field(unsigned long, total_vm)
|
|
__field(unsigned long, anon_rss)
|
|
__field(unsigned long, file_rss)
|
|
__field(unsigned long, shmem_rss)
|
|
__field(uid_t, uid)
|
|
__field(unsigned long, pgtables)
|
|
__field(short, oom_score_adj)
|
|
),
|
|
|
|
TP_fast_assign(
|
|
__entry->pid = task->pid;
|
|
__assign_str(comm, task->comm);
|
|
__entry->total_vm = PG_COUNT_TO_KB(task->mm->total_vm);
|
|
__entry->anon_rss = PG_COUNT_TO_KB(get_mm_counter(task->mm, MM_ANONPAGES));
|
|
__entry->file_rss = PG_COUNT_TO_KB(get_mm_counter(task->mm, MM_FILEPAGES));
|
|
__entry->shmem_rss = PG_COUNT_TO_KB(get_mm_counter(task->mm, MM_SHMEMPAGES));
|
|
__entry->uid = uid;
|
|
__entry->pgtables = mm_pgtables_bytes(task->mm) >> 10;
|
|
__entry->oom_score_adj = task->signal->oom_score_adj;
|
|
),
|
|
|
|
TP_printk("pid=%d comm=%s total-vm=%lukB anon-rss=%lukB file-rss:%lukB shmem-rss:%lukB uid=%u pgtables=%lukB oom_score_adj=%hd",
|
|
__entry->pid,
|
|
__get_str(comm),
|
|
__entry->total_vm,
|
|
__entry->anon_rss,
|
|
__entry->file_rss,
|
|
__entry->shmem_rss,
|
|
__entry->uid,
|
|
__entry->pgtables,
|
|
__entry->oom_score_adj
|
|
)
|
|
);
|
|
|
|
TRACE_EVENT(wake_reaper,
|
|
TP_PROTO(int pid),
|
|
|
|
TP_ARGS(pid),
|
|
|
|
TP_STRUCT__entry(
|
|
__field(int, pid)
|
|
),
|
|
|
|
TP_fast_assign(
|
|
__entry->pid = pid;
|
|
),
|
|
|
|
TP_printk("pid=%d", __entry->pid)
|
|
);
|
|
|
|
TRACE_EVENT(start_task_reaping,
|
|
TP_PROTO(int pid),
|
|
|
|
TP_ARGS(pid),
|
|
|
|
TP_STRUCT__entry(
|
|
__field(int, pid)
|
|
),
|
|
|
|
TP_fast_assign(
|
|
__entry->pid = pid;
|
|
),
|
|
|
|
TP_printk("pid=%d", __entry->pid)
|
|
);
|
|
|
|
TRACE_EVENT(finish_task_reaping,
|
|
TP_PROTO(int pid),
|
|
|
|
TP_ARGS(pid),
|
|
|
|
TP_STRUCT__entry(
|
|
__field(int, pid)
|
|
),
|
|
|
|
TP_fast_assign(
|
|
__entry->pid = pid;
|
|
),
|
|
|
|
TP_printk("pid=%d", __entry->pid)
|
|
);
|
|
|
|
TRACE_EVENT(skip_task_reaping,
|
|
TP_PROTO(int pid),
|
|
|
|
TP_ARGS(pid),
|
|
|
|
TP_STRUCT__entry(
|
|
__field(int, pid)
|
|
),
|
|
|
|
TP_fast_assign(
|
|
__entry->pid = pid;
|
|
),
|
|
|
|
TP_printk("pid=%d", __entry->pid)
|
|
);
|
|
|
|
#ifdef CONFIG_COMPACTION
|
|
TRACE_EVENT(compact_retry,
|
|
|
|
TP_PROTO(int order,
|
|
enum compact_priority priority,
|
|
enum compact_result result,
|
|
int retries,
|
|
int max_retries,
|
|
bool ret),
|
|
|
|
TP_ARGS(order, priority, result, retries, max_retries, ret),
|
|
|
|
TP_STRUCT__entry(
|
|
__field( int, order)
|
|
__field( int, priority)
|
|
__field( int, result)
|
|
__field( int, retries)
|
|
__field( int, max_retries)
|
|
__field( bool, ret)
|
|
),
|
|
|
|
TP_fast_assign(
|
|
__entry->order = order;
|
|
__entry->priority = priority;
|
|
__entry->result = compact_result_to_feedback(result);
|
|
__entry->retries = retries;
|
|
__entry->max_retries = max_retries;
|
|
__entry->ret = ret;
|
|
),
|
|
|
|
TP_printk("order=%d priority=%s compaction_result=%s retries=%d max_retries=%d should_retry=%d",
|
|
__entry->order,
|
|
__print_symbolic(__entry->priority, COMPACTION_PRIORITY),
|
|
__print_symbolic(__entry->result, COMPACTION_FEEDBACK),
|
|
__entry->retries, __entry->max_retries,
|
|
__entry->ret)
|
|
);
|
|
#endif /* CONFIG_COMPACTION */
|
|
#endif
|
|
|
|
/* This part must be outside protection */
|
|
#include <trace/define_trace.h>
|