From: Xiang Gao <gxxa03070307@gmail.com>
To: Steven Rostedt <rostedt@goodmis.org>
Cc: Masami Hiramatsu <mhiramat@kernel.org>,
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 1/2] tracing: add ring-buffer memory usage statistics in tracefs
Date: Sat, 5 Sep 2026 19:27:31 +0800 [thread overview]
Message-ID: <20260905112732.3705405-2-gaoxiang17@xiaomi.com> (raw)
In-Reply-To: <20260905112732.3705405-1-gaoxiang17@xiaomi.com>
Report the memory consumed by the tracing ring buffers, rather than the
usable data capacity exposed by buffer_size_kb. Android low-memory
diagnostics need this to attribute the memory used by tracing when
calculating lost RAM.
The buffers can be spread across the global trace array, dynamically
created instances, and snapshot buffers. Userspace currently has to
discover and sum every instance, and snapshot memory is not exposed by
the per-instance totals.
Add a trace_stats directory with memory_usage_kb reporting:
buffers:
snapshot_buffers:
covering the global trace array and all instances across all CPUs.
The values account for the full pages backing the data sub-buffers and
reader page, plus the cached read page and mmap metadata page when
present. Slab-allocated ring-buffer metadata is not included, as it is
already reported through Slab and would be double-counted when
subtracting tracing memory from lost RAM. Range and remote buffers,
whose pages are externally owned, report zero.
Signed-off-by: Xiang Gao <gaoxiang17@xiaomi.com>
---
Documentation/trace/ftrace.rst | 12 +++++++
include/linux/ring_buffer.h | 1 +
kernel/trace/ring_buffer.c | 41 +++++++++++++++++++++++
kernel/trace/trace.c | 60 ++++++++++++++++++++++++++++++++++
4 files changed, 114 insertions(+)
diff --git a/Documentation/trace/ftrace.rst b/Documentation/trace/ftrace.rst
index 84f06bf0da9b..ff9d604dd1b8 100644
--- a/Documentation/trace/ftrace.rst
+++ b/Documentation/trace/ftrace.rst
@@ -218,6 +218,18 @@ of ftrace. Here is a list of some of the key files:
This displays the total combined size of all the trace buffers.
+ trace_stats/memory_usage_kb:
+
+ This reports the memory consumed by the ring buffers, as opposed to
+ the usable data capacity shown by buffer_size_kb. The value covers the
+ main and snapshot buffers of the global trace array and all tracing
+ instances. It does not include slab-allocated ring-buffer metadata.
+
+ Output::
+
+ buffers: ...
+ snapshot_buffers: ...
+
buffer_subbuf_size_kb:
This sets or displays the sub buffer size. The ring buffer is broken up
diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h
index 0670742b2d60..64eded40222c 100644
--- a/include/linux/ring_buffer.h
+++ b/include/linux/ring_buffer.h
@@ -166,6 +166,7 @@ int ring_buffer_iter_empty(struct ring_buffer_iter *iter);
bool ring_buffer_iter_dropped(struct ring_buffer_iter *iter);
unsigned long ring_buffer_size(struct trace_buffer *buffer, int cpu);
+unsigned long ring_buffer_memory_size(struct trace_buffer *buffer, int cpu);
unsigned long ring_buffer_max_event_size(struct trace_buffer *buffer);
void ring_buffer_reset_cpu(struct trace_buffer *buffer, int cpu);
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 8e2485bb3aa8..a8719b517798 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -6464,6 +6464,47 @@ unsigned long ring_buffer_size(struct trace_buffer *buffer, int cpu)
}
EXPORT_SYMBOL_GPL(ring_buffer_size);
+/**
+ * ring_buffer_memory_size - return the memory used by the buffer (in bytes)
+ * @buffer: The ring buffer.
+ * @cpu: The CPU to get ring buffer memory from.
+ *
+ * Returns the page-allocator memory consumed by @cpu, including the data
+ * sub-buffers, the reader page, the cached read page, and the mmap
+ * metadata page. Unlike ring_buffer_size(), which reports the usable data
+ * capacity, this accounts for the full pages allocated to the buffer.
+ * Range and remote buffers do not own page-allocator memory and report zero.
+ */
+unsigned long ring_buffer_memory_size(struct trace_buffer *buffer, int cpu)
+{
+ struct ring_buffer_per_cpu *cpu_buffer;
+ unsigned long subbuf_size;
+ unsigned long size;
+
+ if (!cpumask_test_cpu(cpu, buffer->cpumask))
+ return 0;
+
+ /* Range and remote buffers use externally owned memory. */
+ if (buffer->range_addr_start || buffer->remote)
+ return 0;
+
+ cpu_buffer = buffer->buffers[cpu];
+ subbuf_size = PAGE_SIZE << buffer->subbuf_order;
+
+ /* Data sub-buffers plus the reader page. */
+ size = (cpu_buffer->nr_pages + 1) * subbuf_size;
+
+ /* The cached read page, if present, is a full sub-buffer page. */
+ if (cpu_buffer->free_page)
+ size += subbuf_size;
+
+ /* The mmap metadata page is a single system page. */
+ if (cpu_buffer->meta_page)
+ size += PAGE_SIZE;
+
+ return size;
+}
+
/**
* ring_buffer_max_event_size - return the max data size of an event
* @buffer: The ring buffer.
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 01a5e87af299..b343e03a6cf8 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -5769,6 +5769,52 @@ tracing_total_entries_read(struct file *filp, char __user *ubuf,
return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
}
+struct trace_mem_stats {
+ unsigned long buffers;
+ unsigned long snapshot;
+};
+
+static void
+trace_array_buffer_memory(struct trace_array *tr, int cpu,
+ unsigned long *buffers, unsigned long *snapshot)
+{
+ if (tr->array_buffer.buffer)
+ *buffers += ring_buffer_memory_size(tr->array_buffer.buffer, cpu);
+
+#ifdef CONFIG_TRACER_SNAPSHOT
+ if (tr->snapshot_buffer.buffer)
+ *snapshot += 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.buffers,
+ &stats.snapshot);
+ }
+
+ return stats;
+}
+
+static int trace_mem_show(struct seq_file *m, void *v)
+{
+ struct trace_mem_stats stats = trace_buffers_memory();
+
+ seq_printf(m, "buffers: %lu\n", stats.buffers >> 10);
+ seq_printf(m, "snapshot_buffers: %lu\n", stats.snapshot >> 10);
+
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(trace_mem);
+
#define LAST_BOOT_HEADER ((void *)1)
static void *l_next(struct seq_file *m, void *v, loff_t *pos)
@@ -9188,6 +9234,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)
{
@@ -9196,6 +9254,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-09-05 11:27 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-05 11:27 [PATCH 0/2] tracing: add ring-buffer memory usage statistics Xiang Gao
2026-09-05 11:27 ` Xiang Gao [this message]
2026-09-05 11:38 ` [PATCH 1/2] tracing: add ring-buffer memory usage statistics in tracefs sashiko-bot
2026-09-05 11:27 ` [PATCH 2/2] tracing: add per-CPU " 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=20260905112732.3705405-2-gaoxiang17@xiaomi.com \
--to=gxxa03070307@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=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