From: Xiang Gao <gxxa03070307@gmail.com>
To: Steven Rostedt <rostedt@goodmis.org>,
Vincent Donnefort <vdonnefort@google.com>,
Masami Hiramatsu <mhiramat@kernel.org>,
Donggeun Yoo <donggeunyoo.kernel@gmail.com>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>,
Lorenzo Stoakes <ljs@kernel.org>, gao xu <gaoxu2@honor.com>,
yinchuang1@xiaomi.com, linux-trace-kernel@vger.kernel.org,
linux-kernel@vger.kernel.org, Xiang Gao <gaoxiang17@xiaomi.com>
Subject: [PATCH v5 2/4] tracing: add aggregate buffer memory usage statistics
Date: Thu, 5 Nov 2026 22:02:19 +0800 [thread overview]
Message-ID: <20261105140221.44614-3-gaoxiang17@xiaomi.com> (raw)
In-Reply-To: <20261105140221.44614-1-gaoxiang17@xiaomi.com>
Add a trace_stats directory with memory_usage_kb reporting the page
memory consumed by the tracing ring buffers, categorized by buffer type
and memory source:
global:
instances:
snapshots:
persistents:
remotes:
total_system:
total_carveout:
The global, instances, and snapshots values come from the page
allocator. Persistent buffers use reserved memory and are reported under
persistents, while the backup instance uses vmalloc and is skipped since
it is already accounted in VmallocUsed. Remote buffers are not yet
enumerated and report zero.
total_system is the page-allocator memory that contributes to lost RAM,
while total_carveout is reserved memory that was never in the free pool.
Signed-off-by: Xiang Gao <gaoxiang17@xiaomi.com>
---
kernel/trace/trace.c | 115 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 115 insertions(+)
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index e8c4efa8107b..6036e368fe10 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -5797,6 +5797,107 @@ tracing_total_capacity_read(struct file *filp, char __user *ubuf, size_t cnt, lo
return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
}
+struct trace_mem_stats {
+ unsigned long global;
+ unsigned long instances;
+ unsigned long snapshots;
+ unsigned long persistents;
+ unsigned long remotes;
+ unsigned long total_system;
+ unsigned long total_carveout;
+};
+
+static void
+trace_array_buffer_memory(struct trace_array *tr, int cpu,
+ struct trace_mem_stats *stats)
+{
+ if (tr->range_addr_start) {
+ /*
+ * Persistent buffers use reserved memory (carveout). The
+ * backup instance uses vmalloc and is already accounted in
+ * VmallocUsed, so skip it.
+ */
+ if (!(tr->flags & TRACE_ARRAY_FL_VMALLOC))
+ stats->persistents +=
+ ring_buffer_memory_size(tr->array_buffer.buffer, cpu);
+ } else if (tr->flags & TRACE_ARRAY_FL_GLOBAL) {
+ stats->global +=
+ ring_buffer_memory_size(tr->array_buffer.buffer, cpu);
+ } else {
+ stats->instances +=
+ ring_buffer_memory_size(tr->array_buffer.buffer, cpu);
+ }
+
+#ifdef CONFIG_TRACER_SNAPSHOT
+ if (tr->snapshot_buffer.buffer)
+ stats->snapshots +=
+ ring_buffer_memory_size(tr->snapshot_buffer.buffer, cpu);
+#endif
+}
+
+static struct trace_mem_stats trace_buffers_memory(void)
+{
+ struct trace_mem_stats stats = {};
+ struct trace_array *tr;
+ int cpu;
+
+ guard(mutex)(&trace_types_lock);
+
+ list_for_each_entry(tr, &ftrace_trace_arrays, list) {
+ for_each_tracing_cpu(cpu)
+ trace_array_buffer_memory(tr, cpu, &stats);
+ }
+
+ /*
+ * temp_buffer is allocated in tracer_alloc_buffers() and is never
+ * attached to a trace array. It temporarily holds event data for
+ * triggers when tracing is off. Account for its pages too.
+ */
+ if (temp_buffer) {
+ for_each_tracing_cpu(cpu)
+ stats.global += ring_buffer_memory_size(temp_buffer, cpu);
+ }
+
+ stats.total_system = stats.global + stats.instances +
+ stats.snapshots + stats.remotes;
+ stats.total_carveout = stats.persistents;
+
+ return stats;
+}
+
+static int trace_mem_show(struct seq_file *m, void *v)
+{
+ struct trace_mem_stats stats = trace_buffers_memory();
+
+ seq_printf(m, "global: %lu\n", stats.global >> 10);
+ seq_printf(m, "instances: %lu\n", stats.instances >> 10);
+ seq_printf(m, "snapshots: %lu\n", stats.snapshots >> 10);
+ seq_printf(m, "persistents: %lu\n", stats.persistents >> 10);
+ seq_printf(m, "remotes: %lu\n", stats.remotes >> 10);
+ seq_printf(m, "total_system: %lu\n", stats.total_system >> 10);
+ seq_printf(m, "total_carveout: %lu\n", stats.total_carveout >> 10);
+
+ return 0;
+}
+
+static int trace_mem_open(struct inode *inode, struct file *file)
+{
+ int ret;
+
+ ret = tracing_check_open_get_tr(NULL);
+ if (ret)
+ return ret;
+
+ return single_open(file, trace_mem_show, inode->i_private);
+}
+
+static const struct file_operations trace_mem_fops = {
+ .open = trace_mem_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
#define LAST_BOOT_HEADER ((void *)1)
static void *l_next(struct seq_file *m, void *v, loff_t *pos)
@@ -9313,6 +9414,18 @@ static struct notifier_block trace_module_nb = {
};
#endif /* CONFIG_MODULES */
+static __init void init_trace_stats_tracefs(void)
+{
+ struct dentry *stats_dir;
+
+ stats_dir = tracefs_create_dir("trace_stats", NULL);
+ if (!stats_dir)
+ return;
+
+ trace_create_file("memory_usage_kb", TRACE_MODE_READ, stats_dir,
+ NULL, &trace_mem_fops);
+}
+
static __init void tracer_init_tracefs_work_func(struct work_struct *work)
{
/*
@@ -9327,6 +9440,8 @@ static __init void tracer_init_tracefs_work_func(struct work_struct *work)
init_tracer_tracefs(&global_trace, NULL);
ftrace_init_tracefs_toplevel(&global_trace, NULL);
+ init_trace_stats_tracefs();
+
trace_create_file("tracing_thresh", TRACE_MODE_WRITE, NULL,
&global_trace, &tracing_thresh_fops);
--
2.34.1
next prev parent reply other threads:[~2026-11-05 14:02 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-05 14:02 [PATCH v5 0/4] tracing: add ring-buffer " Xiang Gao
2026-11-05 14:02 ` [PATCH v5 1/4] ring-buffer: add ring_buffer_memory_size() Xiang Gao
2026-11-05 14:02 ` Xiang Gao [this message]
2026-11-05 14:02 ` [PATCH v5 3/4] tracing: add per-CPU buffer memory usage statistics Xiang Gao
2026-11-05 14:02 ` [PATCH v5 4/4] Documentation: document trace_stats memory_usage_kb Xiang Gao
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261105140221.44614-3-gaoxiang17@xiaomi.com \
--to=gxxa03070307@gmail.com \
--cc=donggeunyoo.kernel@gmail.com \
--cc=gaoxiang17@xiaomi.com \
--cc=gaoxu2@honor.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=ljs@kernel.org \
--cc=mathieu.desnoyers@efficios.com \
--cc=mhiramat@kernel.org \
--cc=rostedt@goodmis.org \
--cc=vdonnefort@google.com \
--cc=yinchuang1@xiaomi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®