Linux Trace Kernel
 help / color / mirror / Atom feed
* [PATCH 0/2] tracing: add ring-buffer memory usage statistics
@ 2026-09-05 11:27 Xiang Gao
  2026-09-05 11:27 ` [PATCH 1/2] tracing: add ring-buffer memory usage statistics in tracefs Xiang Gao
                   ` (3 more replies)
  0 siblings, 4 replies; 11+ messages in thread
From: Xiang Gao @ 2026-09-05 11:27 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Masami Hiramatsu, Mathieu Desnoyers, Lorenzo Stoakes, gao xu,
	yinchuang1, linux-trace-kernel, linux-kernel, Xiang Gao

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.

Patch 1 adds:

  /sys/kernel/tracing/trace_stats/memory_usage_kb

reporting:

  buffers: ...
  snapshot_buffers: ...

covering the global trace array and all instances across all CPUs.

Patch 2 adds the per-CPU view under
trace_stats/per_cpu/cpuN/memory_usage_kb.

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.

Xiang Gao (2):
  tracing: add ring-buffer memory usage statistics in tracefs
  tracing: add per-CPU memory usage statistics in tracefs

 Documentation/trace/ftrace.rst |  15 +++++
 include/linux/ring_buffer.h    |   1 +
 kernel/trace/ring_buffer.c     |  41 +++++++++++++
 kernel/trace/trace.c           | 104 +++++++++++++++++++++++++++++++++
 4 files changed, 161 insertions(+)

-- 
2.34.1


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

* [PATCH 1/2] tracing: add ring-buffer memory usage statistics in tracefs
  2026-09-05 11:27 [PATCH 0/2] tracing: add ring-buffer memory usage statistics Xiang Gao
@ 2026-09-05 11:27 ` Xiang Gao
  2026-09-05 11:38   ` sashiko-bot
  2026-09-07  9:26   ` Vincent Donnefort
  2026-09-05 11:27 ` [PATCH 2/2] tracing: add per-CPU " Xiang Gao
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 11+ messages in thread
From: Xiang Gao @ 2026-09-05 11:27 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Masami Hiramatsu, Mathieu Desnoyers, Lorenzo Stoakes, gao xu,
	yinchuang1, linux-trace-kernel, linux-kernel, Xiang Gao

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


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

* [PATCH 2/2] tracing: add per-CPU memory usage statistics in tracefs
  2026-09-05 11:27 [PATCH 0/2] tracing: add ring-buffer memory usage statistics Xiang Gao
  2026-09-05 11:27 ` [PATCH 1/2] tracing: add ring-buffer memory usage statistics in tracefs Xiang Gao
@ 2026-09-05 11:27 ` Xiang Gao
  2026-09-11 15:50 ` [PATCH v2 0/2] tracing: add ring-buffer memory usage statistics Xiang Gao
  2026-09-11 17:22 ` [PATCH 0/2] tracing: add ring-buffer memory usage statistics Vincent Donnefort
  3 siblings, 0 replies; 11+ messages in thread
From: Xiang Gao @ 2026-09-05 11:27 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Masami Hiramatsu, Mathieu Desnoyers, Lorenzo Stoakes, gao xu,
	yinchuang1, linux-trace-kernel, linux-kernel, Xiang Gao

Provide a per-CPU view of the tracing ring-buffer memory usage under
trace_stats/per_cpu/cpuN/memory_usage_kb, using the same format as the
aggregate file. Each file reports only the buffers belonging to that CPU
across the global trace array and all tracing instances.

Signed-off-by: Xiang Gao <gaoxiang17@xiaomi.com>
---
 Documentation/trace/ftrace.rst |  3 +++
 kernel/trace/trace.c           | 46 +++++++++++++++++++++++++++++++++-
 2 files changed, 48 insertions(+), 1 deletion(-)

diff --git a/Documentation/trace/ftrace.rst b/Documentation/trace/ftrace.rst
index ff9d604dd1b8..694c9ed8f241 100644
--- a/Documentation/trace/ftrace.rst
+++ b/Documentation/trace/ftrace.rst
@@ -230,6 +230,9 @@ of ftrace. Here is a list of some of the key files:
 	    buffers: ...
 	    snapshot_buffers: ...
 
+	The same file is provided under trace_stats/per_cpu/cpuN/, reporting
+	only the buffers belonging to that CPU.
+
   buffer_subbuf_size_kb:
 
 	This sets or displays the sub buffer size. The ring buffer is broken up
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index b343e03a6cf8..ea05077af4a0 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -5815,6 +5815,31 @@ static int trace_mem_show(struct seq_file *m, void *v)
 }
 DEFINE_SHOW_ATTRIBUTE(trace_mem);
 
+static struct trace_mem_stats trace_buffers_memory_cpu(int cpu)
+{
+	struct trace_mem_stats stats = {};
+	struct trace_array *tr;
+
+	guard(mutex)(&trace_types_lock);
+
+	list_for_each_entry(tr, &ftrace_trace_arrays, list)
+		trace_array_buffer_memory(tr, cpu, &stats.buffers,
+					  &stats.snapshot);
+
+	return stats;
+}
+
+static int trace_mem_per_cpu_show(struct seq_file *m, void *v)
+{
+	struct trace_mem_stats stats = trace_buffers_memory_cpu((long)m->private);
+
+	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_per_cpu);
+
 #define LAST_BOOT_HEADER ((void *)1)
 
 static void *l_next(struct seq_file *m, void *v, loff_t *pos)
@@ -9236,7 +9261,9 @@ static struct notifier_block trace_module_nb = {
 
 static __init void init_trace_stats_tracefs(void)
 {
-	struct dentry *stats_dir;
+	struct dentry *stats_dir, *per_cpu_dir, *cpu_dir;
+	char cpu_dir_name[30];
+	int cpu;
 
 	stats_dir = tracefs_create_dir("trace_stats", NULL);
 	if (!stats_dir)
@@ -9244,6 +9271,23 @@ static __init void init_trace_stats_tracefs(void)
 
 	trace_create_file("memory_usage_kb", TRACE_MODE_READ, stats_dir,
 			  NULL, &trace_mem_fops);
+
+	per_cpu_dir = tracefs_create_dir("per_cpu", stats_dir);
+	if (!per_cpu_dir)
+		return;
+
+	for_each_tracing_cpu(cpu) {
+		snprintf(cpu_dir_name, 30, "cpu%d", cpu);
+		cpu_dir = tracefs_create_dir(cpu_dir_name, per_cpu_dir);
+		if (!cpu_dir) {
+			pr_warn("Could not create tracefs '%s' entry\n",
+				cpu_dir_name);
+			continue;
+		}
+
+		trace_create_file("memory_usage_kb", TRACE_MODE_READ, cpu_dir,
+				  (void *)(long)cpu, &trace_mem_per_cpu_fops);
+	}
 }
 
 static __init void tracer_init_tracefs_work_func(struct work_struct *work)
-- 
2.34.1


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

* Re: [PATCH 1/2] tracing: add ring-buffer memory usage statistics in tracefs
  2026-09-05 11:27 ` [PATCH 1/2] tracing: add ring-buffer memory usage statistics in tracefs Xiang Gao
@ 2026-09-05 11:38   ` sashiko-bot
  2026-09-07  9:26   ` Vincent Donnefort
  1 sibling, 0 replies; 11+ messages in thread
From: sashiko-bot @ 2026-09-05 11:38 UTC (permalink / raw)
  To: Xiang Gao; +Cc: linux-trace-kernel

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] Compilation failure due to evaluating a struct type in a boolean context.
--

commit 59684c76ae178c23d488e6128dbc2d350cbbec1d
Author: Xiang Gao <gxxa03070307@gmail.com>

tracing: add ring-buffer memory usage statistics in tracefs

This commit adds memory consumption statistics for tracing ring buffers to
tracefs. It reports the memory consumed by the main and snapshot buffers
across all instances, tracking the full pages backing the sub-buffers.

> diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
> index 5fc009edc1ec9..4579053d34ec4 100644
> --- a/kernel/trace/ring_buffer.c
> +++ b/kernel/trace/ring_buffer.c

[ ... ]

> @@ -6526,6 +6526,47 @@ unsigned long ring_buffer_size(struct trace_buffer *buffer, int cpu)

[ ... ]

> +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)

[Severity: Low]
Does this code cause a compilation failure?

The free_page member of struct ring_buffer_per_cpu is an embedded struct
(struct buffer_data_read_page), rather than a pointer. Evaluating it
directly in a boolean context will cause a compiler error because a scalar
value is required.

Should this condition check a field within the struct instead, such as
cpu_buffer->free_page.data?

> +		size += subbuf_size;
> +
> +	/* The mmap metadata page is a single system page. */
> +	if (cpu_buffer->meta_page)
> +		size += PAGE_SIZE;
> +
> +	return size;
> +}

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260905112732.3705405-1-gaoxiang17@xiaomi.com?part=1

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

* Re: [PATCH 1/2] tracing: add ring-buffer memory usage statistics in tracefs
  2026-09-05 11:27 ` [PATCH 1/2] tracing: add ring-buffer memory usage statistics in tracefs Xiang Gao
  2026-09-05 11:38   ` sashiko-bot
@ 2026-09-07  9:26   ` Vincent Donnefort
  1 sibling, 0 replies; 11+ messages in thread
From: Vincent Donnefort @ 2026-09-07  9:26 UTC (permalink / raw)
  To: Xiang Gao
  Cc: Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers,
	Lorenzo Stoakes, gao xu, yinchuang1, linux-trace-kernel,
	linux-kernel, Xiang Gao

On Sat, Sep 05, 2026 at 07:27:31PM +0800, Xiang Gao wrote:
> 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;

Hum, why not including that? This is still memory immobilised for tracing.
(notice though remote buffers wouldn't appear in ftrace_trace_arrays)

> +
> +	cpu_buffer = buffer->buffers[cpu];
> +	subbuf_size = PAGE_SIZE << buffer->subbuf_order;

READ_ONCE(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
> 
> 

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

* [PATCH v2 0/2] tracing: add ring-buffer memory usage statistics
  2026-09-05 11:27 [PATCH 0/2] tracing: add ring-buffer memory usage statistics Xiang Gao
  2026-09-05 11:27 ` [PATCH 1/2] tracing: add ring-buffer memory usage statistics in tracefs Xiang Gao
  2026-09-05 11:27 ` [PATCH 2/2] tracing: add per-CPU " Xiang Gao
@ 2026-09-11 15:50 ` Xiang Gao
  2026-09-11 15:50   ` [PATCH v2 1/2] tracing: add ring-buffer memory usage statistics in tracefs Xiang Gao
  2026-09-11 15:50   ` [PATCH v2 2/2] tracing: add per-CPU " Xiang Gao
  2026-09-11 17:22 ` [PATCH 0/2] tracing: add ring-buffer memory usage statistics Vincent Donnefort
  3 siblings, 2 replies; 11+ messages in thread
From: Xiang Gao @ 2026-09-11 15:50 UTC (permalink / raw)
  To: Steven Rostedt, Vincent Donnefort
  Cc: Masami Hiramatsu, Mathieu Desnoyers, Lorenzo Stoakes, gao xu,
	yinchuang1, linux-trace-kernel, linux-kernel, Xiang Gao

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.

Patch 1 adds:

  /sys/kernel/tracing/trace_stats/memory_usage_kb

reporting:

  buffers: ...
  snapshot_buffers: ...

covering the global trace array and all instances across all CPUs.

Patch 2 adds the per-CPU view under
trace_stats/per_cpu/cpuN/memory_usage_kb.

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.

Changes since v1:
- Include range buffers in the accounting (Vincent Donnefort).
- Use READ_ONCE() for buffer->subbuf_order (Vincent Donnefort).
- Keep remote buffers excluded.

Xiang Gao (2):
  tracing: add ring-buffer memory usage statistics in tracefs
  tracing: add per-CPU memory usage statistics in tracefs

 Documentation/trace/ftrace.rst |  15 +++++
 include/linux/ring_buffer.h    |   1 +
 kernel/trace/ring_buffer.c     |  41 +++++++++++++
 kernel/trace/trace.c           | 104 +++++++++++++++++++++++++++++++++
 4 files changed, 161 insertions(+)

-- 
2.34.1


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

* [PATCH v2 1/2] tracing: add ring-buffer memory usage statistics in tracefs
  2026-09-11 15:50 ` [PATCH v2 0/2] tracing: add ring-buffer memory usage statistics Xiang Gao
@ 2026-09-11 15:50   ` Xiang Gao
  2026-09-11 16:04     ` sashiko-bot
  2026-09-13 16:37     ` Donggeun Yoo
  2026-09-11 15:50   ` [PATCH v2 2/2] tracing: add per-CPU " Xiang Gao
  1 sibling, 2 replies; 11+ messages in thread
From: Xiang Gao @ 2026-09-11 15:50 UTC (permalink / raw)
  To: Steven Rostedt, Vincent Donnefort
  Cc: Masami Hiramatsu, Mathieu Desnoyers, Lorenzo Stoakes, gao xu,
	yinchuang1, linux-trace-kernel, linux-kernel, Xiang Gao

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. 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..292af4807c70 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.
+ * 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;
+
+	/* Remote buffers use externally owned memory. */
+	if (buffer->remote)
+		return 0;
+
+	cpu_buffer = buffer->buffers[cpu];
+	subbuf_size = PAGE_SIZE << READ_ONCE(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


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

* [PATCH v2 2/2] tracing: add per-CPU memory usage statistics in tracefs
  2026-09-11 15:50 ` [PATCH v2 0/2] tracing: add ring-buffer memory usage statistics Xiang Gao
  2026-09-11 15:50   ` [PATCH v2 1/2] tracing: add ring-buffer memory usage statistics in tracefs Xiang Gao
@ 2026-09-11 15:50   ` Xiang Gao
  1 sibling, 0 replies; 11+ messages in thread
From: Xiang Gao @ 2026-09-11 15:50 UTC (permalink / raw)
  To: Steven Rostedt, Vincent Donnefort
  Cc: Masami Hiramatsu, Mathieu Desnoyers, Lorenzo Stoakes, gao xu,
	yinchuang1, linux-trace-kernel, linux-kernel, Xiang Gao

Provide a per-CPU view of the tracing ring-buffer memory usage under
trace_stats/per_cpu/cpuN/memory_usage_kb, using the same format as the
aggregate file. Each file reports only the buffers belonging to that CPU
across the global trace array and all tracing instances.

Signed-off-by: Xiang Gao <gaoxiang17@xiaomi.com>
---
 Documentation/trace/ftrace.rst |  3 +++
 kernel/trace/trace.c           | 46 +++++++++++++++++++++++++++++++++-
 2 files changed, 48 insertions(+), 1 deletion(-)

diff --git a/Documentation/trace/ftrace.rst b/Documentation/trace/ftrace.rst
index ff9d604dd1b8..694c9ed8f241 100644
--- a/Documentation/trace/ftrace.rst
+++ b/Documentation/trace/ftrace.rst
@@ -230,6 +230,9 @@ of ftrace. Here is a list of some of the key files:
 	    buffers: ...
 	    snapshot_buffers: ...
 
+	The same file is provided under trace_stats/per_cpu/cpuN/, reporting
+	only the buffers belonging to that CPU.
+
   buffer_subbuf_size_kb:
 
 	This sets or displays the sub buffer size. The ring buffer is broken up
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index b343e03a6cf8..ea05077af4a0 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -5815,6 +5815,31 @@ static int trace_mem_show(struct seq_file *m, void *v)
 }
 DEFINE_SHOW_ATTRIBUTE(trace_mem);
 
+static struct trace_mem_stats trace_buffers_memory_cpu(int cpu)
+{
+	struct trace_mem_stats stats = {};
+	struct trace_array *tr;
+
+	guard(mutex)(&trace_types_lock);
+
+	list_for_each_entry(tr, &ftrace_trace_arrays, list)
+		trace_array_buffer_memory(tr, cpu, &stats.buffers,
+					  &stats.snapshot);
+
+	return stats;
+}
+
+static int trace_mem_per_cpu_show(struct seq_file *m, void *v)
+{
+	struct trace_mem_stats stats = trace_buffers_memory_cpu((long)m->private);
+
+	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_per_cpu);
+
 #define LAST_BOOT_HEADER ((void *)1)
 
 static void *l_next(struct seq_file *m, void *v, loff_t *pos)
@@ -9236,7 +9261,9 @@ static struct notifier_block trace_module_nb = {
 
 static __init void init_trace_stats_tracefs(void)
 {
-	struct dentry *stats_dir;
+	struct dentry *stats_dir, *per_cpu_dir, *cpu_dir;
+	char cpu_dir_name[30];
+	int cpu;
 
 	stats_dir = tracefs_create_dir("trace_stats", NULL);
 	if (!stats_dir)
@@ -9244,6 +9271,23 @@ static __init void init_trace_stats_tracefs(void)
 
 	trace_create_file("memory_usage_kb", TRACE_MODE_READ, stats_dir,
 			  NULL, &trace_mem_fops);
+
+	per_cpu_dir = tracefs_create_dir("per_cpu", stats_dir);
+	if (!per_cpu_dir)
+		return;
+
+	for_each_tracing_cpu(cpu) {
+		snprintf(cpu_dir_name, 30, "cpu%d", cpu);
+		cpu_dir = tracefs_create_dir(cpu_dir_name, per_cpu_dir);
+		if (!cpu_dir) {
+			pr_warn("Could not create tracefs '%s' entry\n",
+				cpu_dir_name);
+			continue;
+		}
+
+		trace_create_file("memory_usage_kb", TRACE_MODE_READ, cpu_dir,
+				  (void *)(long)cpu, &trace_mem_per_cpu_fops);
+	}
 }
 
 static __init void tracer_init_tracefs_work_func(struct work_struct *work)
-- 
2.34.1


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

* Re: [PATCH v2 1/2] tracing: add ring-buffer memory usage statistics in tracefs
  2026-09-11 15:50   ` [PATCH v2 1/2] tracing: add ring-buffer memory usage statistics in tracefs Xiang Gao
@ 2026-09-11 16:04     ` sashiko-bot
  2026-09-13 16:37     ` Donggeun Yoo
  1 sibling, 0 replies; 11+ messages in thread
From: sashiko-bot @ 2026-09-11 16:04 UTC (permalink / raw)
  To: Xiang Gao; +Cc: linux-trace-kernel

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] Persistent memory-mapped trace buffers are incorrectly accounted as page-allocator memory, leading to double-counting in lost RAM calculations.
- [Low] Evaluation of a struct type as a boolean condition causes a hard compilation error.
--

commit 339a95b19ea8f13ff179992c9814bfee94fa38b3
Author: Xiang Gao <gxxa03070307@gmail.com>

tracing: add ring-buffer memory usage statistics in tracefs

This commit adds memory usage reporting for tracing ring buffers to calculate
memory footprint more accurately than relying on buffer capacity. It exposes
a new memory_usage_kb file in tracefs which sums up the page allocator memory
used by the data pages and reader pages.

> diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
> index 9c03a555a6ba2..73e79c86035c2 100644
> --- a/kernel/trace/ring_buffer.c
> +++ b/kernel/trace/ring_buffer.c
[ ... ]
> @@ -6560,6 +6560,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)
[ ... ]
> + */
> +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;
> +
> +	/* Remote buffers use externally owned memory. */
> +	if (buffer->remote)
> +		return 0;

[Severity: Medium]
Does this check also need to exclude persistent memory-mapped trace buffers
where buffer->range_addr_start is set? Since those buffers also use
externally owned or reserved memory bypassing the page-allocator, not
skipping them here might result in double-counting their memory in lost
RAM calculations.

> +
> +	cpu_buffer = buffer->buffers[cpu];
> +	subbuf_size = PAGE_SIZE << READ_ONCE(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;

[Severity: Low]
Does evaluating cpu_buffer->free_page directly as a boolean condition
cause a compiler error here, since free_page is an embedded struct
(struct buffer_data_read_page) rather than a pointer? Should this check its
internal data pointer instead, such as if (cpu_buffer->free_page.data)?

> +
> +	/* The mmap metadata page is a single system page. */
> +	if (cpu_buffer->meta_page)
> +		size += PAGE_SIZE;
> +
> +	return size;
> +}

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260911155017.3377254-1-gaoxiang17@xiaomi.com?part=1

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

* Re: [PATCH 0/2] tracing: add ring-buffer memory usage statistics
  2026-09-05 11:27 [PATCH 0/2] tracing: add ring-buffer memory usage statistics Xiang Gao
                   ` (2 preceding siblings ...)
  2026-09-11 15:50 ` [PATCH v2 0/2] tracing: add ring-buffer memory usage statistics Xiang Gao
@ 2026-09-11 17:22 ` Vincent Donnefort
  3 siblings, 0 replies; 11+ messages in thread
From: Vincent Donnefort @ 2026-09-11 17:22 UTC (permalink / raw)
  To: Xiang Gao
  Cc: Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers,
	Lorenzo Stoakes, gao xu, yinchuang1, linux-trace-kernel,
	linux-kernel, Xiang Gao

On Sat, Sep 05, 2026 at 07:27:30PM +0800, Xiang Gao wrote:
> 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.
> 
> Patch 1 adds:
> 
>   /sys/kernel/tracing/trace_stats/memory_usage_kb
> 
> reporting:
> 
>   buffers: ...
>   snapshot_buffers: ...
> 
> covering the global trace array and all instances across all CPUs.
> 
> Patch 2 adds the per-CPU view under
> trace_stats/per_cpu/cpuN/memory_usage_kb.
> 
> 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.
> 
> Xiang Gao (2):
>   tracing: add ring-buffer memory usage statistics in tracefs
>   tracing: add per-CPU memory usage statistics in tracefs
> 
>  Documentation/trace/ftrace.rst |  15 +++++
>  include/linux/ring_buffer.h    |   1 +
>  kernel/trace/ring_buffer.c     |  41 +++++++++++++
>  kernel/trace/trace.c           | 104 +++++++++++++++++++++++++++++++++
>  4 files changed, 161 insertions(+)
> 
> -- 
> 2.34.1
> 
> 

It looks like you have sent the same v1 again.

-- 
Vincent

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

* Re: [PATCH v2 1/2] tracing: add ring-buffer memory usage statistics in tracefs
  2026-09-11 15:50   ` [PATCH v2 1/2] tracing: add ring-buffer memory usage statistics in tracefs Xiang Gao
  2026-09-11 16:04     ` sashiko-bot
@ 2026-09-13 16:37     ` Donggeun Yoo
  1 sibling, 0 replies; 11+ messages in thread
From: Donggeun Yoo @ 2026-09-13 16:37 UTC (permalink / raw)
  To: Xiang Gao
  Cc: Donggeun Yoo, Xiang Gao, Steven Rostedt, Vincent Donnefort,
	Masami Hiramatsu, Mathieu Desnoyers, Lorenzo Stoakes, gao xu,
	yinchuang1, linux-trace-kernel, linux-kernel

On Fri, Sep 11, 2026 at 11:50:16PM +0800, Xiang Gao wrote:
> +	/* The cached read page, if present, is a full sub-buffer page. */
> +	if (cpu_buffer->free_page)
> +		size += subbuf_size;

Have you compile-tested this one? free_page is a struct, not a pointer:

  kernel/trace/ring_buffer.c:6594:13: error: used struct type value where scalar is required
   6594 |         if (cpu_buffer->free_page)
        |             ^~~~~~~~~~

cpu_buffer->free_page.data should do it.

> +	list_for_each_entry(tr, &ftrace_trace_arrays, list) {
> +		for_each_tracing_cpu(cpu)
> +			trace_array_buffer_memory(tr, cpu, &stats.buffers,
> +						  &stats.snapshot);
> +	}

With that fixed the walk does match the changelog, but temp_buffer is out
of its reach. tracer_alloc_buffers() allocates it and never attaches it to
a trace array, so it is not on ftrace_trace_arrays, and its pages are the
kind you are counting: sub-buffers and a reader page from the page
allocator, not remote and not slab.

It is three sub-buffers per CPU at order 0 and is never resized, so it
disappears into the noise once a real buffer is sized up. At rest it does
not. On an 8 CPU x86_64 guest the file reports

  buffers: 96

while temp_buffer holds another 96K. Freeing it hands back 24 pages, which
is what ring_buffer_memory_size() predicts for it.

Was that deliberate? For lost RAM accounting I would have expected it in.

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

end of thread, other threads:[~2026-09-13 16:37 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-05 11:27 [PATCH 0/2] tracing: add ring-buffer memory usage statistics Xiang Gao
2026-09-05 11:27 ` [PATCH 1/2] tracing: add ring-buffer memory usage statistics in tracefs Xiang Gao
2026-09-05 11:38   ` sashiko-bot
2026-09-07  9:26   ` Vincent Donnefort
2026-09-05 11:27 ` [PATCH 2/2] tracing: add per-CPU " Xiang Gao
2026-09-11 15:50 ` [PATCH v2 0/2] tracing: add ring-buffer memory usage statistics Xiang Gao
2026-09-11 15:50   ` [PATCH v2 1/2] tracing: add ring-buffer memory usage statistics in tracefs Xiang Gao
2026-09-11 16:04     ` sashiko-bot
2026-09-13 16:37     ` Donggeun Yoo
2026-09-11 15:50   ` [PATCH v2 2/2] tracing: add per-CPU " Xiang Gao
2026-09-11 17:22 ` [PATCH 0/2] tracing: add ring-buffer memory usage statistics Vincent Donnefort

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