ring-buffer: Add writer_loops to stat file

Started by Steven Rostedt on Jan 19, 2024

Subsystems (3)

Maintainers (4)

DORMANTno replies

open the first message on its own page

Message details and related content
From: "Steven Rostedt (Google)" <rostedt@goodmis.org>

As the ring buffer never had a cmpxchg loop until the reserving logic
added one, add a statistic on how many times it happens. This can be used
to make sure there's not any issues because the writer is retrying.

 ~# cat /sys/kernel/tracing/per_cpu/cpu0/stats
entries: 51226
overrun: 3920945
commit overrun: 0
bytes: 1441376
oldest event ts:  2881.254827
now ts:  2912.011953
dropped events: 0
read events: 0
writer loops: 267

Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
[ Depends on:
  https://lore.kernel.org/linux-trace-kernel/20240118181206.4977da2f@gandalf.local.home/
]

 include/linux/ring_buffer.h |  1 +
 kernel/trace/ring_buffer.c  | 22 +++++++++++++++++++++-
 kernel/trace/trace.c        |  3 +++
 3 files changed, 25 insertions(+), 1 deletion(-)
diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h
index fa802db216f9..f2bd59f24f7a 100644
--- a/include/linux/ring_buffer.h
+++ b/include/linux/ring_buffer.h
@@ -180,6 +180,7 @@ unsigned long ring_buffer_overrun_cpu(struct trace_buffer *buffer, int cpu);
 unsigned long ring_buffer_commit_overrun_cpu(struct trace_buffer *buffer, int cpu);
 unsigned long ring_buffer_dropped_events_cpu(struct trace_buffer *buffer, int cpu);
 unsigned long ring_buffer_read_events_cpu(struct trace_buffer *buffer, int cpu);
+unsigned long ring_buffer_writer_loops(struct trace_buffer *buffer, int cpu);
 
 u64 ring_buffer_time_stamp(struct trace_buffer *buffer);
 void ring_buffer_normalize_time_stamp(struct trace_buffer *buffer,
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 74f8895785ca..a8a32c15c8b6 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -474,6 +474,7 @@ struct ring_buffer_per_cpu {
 	local_t				pages_touched;
 	local_t				pages_lost;
 	local_t				pages_read;
+	local_t				writer_loops;
 	long				last_pages_touch;
 	size_t				shortest_full;
 	unsigned long			read;
@@ -3483,8 +3484,10 @@ __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer,
 
  /*B*/	rb_time_set(&cpu_buffer->before_stamp, info->ts);
 
- /*C*/	if (!local_try_cmpxchg(&tail_page->write, &w, w + info->length))
+ /*C*/	if (!local_try_cmpxchg(&tail_page->write, &w, w + info->length)) {
+		local_inc(&cpu_buffer->writer_loops);
 		goto again;
+	}
 
 	/* Set write to the start of this event */
 	write = w & RB_WRITE_MASK;
@@ -4062,6 +4065,22 @@ u64 ring_buffer_oldest_event_ts(struct trace_buffer *buffer, int cpu)
 }
 EXPORT_SYMBOL_GPL(ring_buffer_oldest_event_ts);
 
+/**
+ * ring_buffer_writer_loops - get the number of times writer failed cmpxchg
+ * @buffer: The ring buffer
+ * @cpu: The per CPU buffer to read from.
+ */
+unsigned long ring_buffer_writer_loops(struct trace_buffer *buffer, int cpu)
+{
+	struct ring_buffer_per_cpu *cpu_buffer;
+
+	if (!cpumask_test_cpu(cpu, buffer->cpumask))
+		return 0;
+
+	cpu_buffer = buffer->buffers[cpu];
+	return local_read(&cpu_buffer->writer_loops);
+}
+
 /**
  * ring_buffer_bytes_cpu - get the number of bytes unconsumed in a cpu buffer
  * @buffer: The ring buffer
@@ -5145,6 +5164,7 @@ rb_reset_cpu(struct ring_buffer_per_cpu *cpu_buffer)
 	local_set(&cpu_buffer->pages_touched, 0);
 	local_set(&cpu_buffer->pages_lost, 0);
 	local_set(&cpu_buffer->pages_read, 0);
+	local_set(&cpu_buffer->writer_loops, 0);
 	cpu_buffer->last_pages_touch = 0;
 	cpu_buffer->shortest_full = 0;
 	cpu_buffer->read = 0;
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 46dbe22121e9..3a5f33c344c4 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -8670,6 +8670,9 @@ tracing_stats_read(struct file *filp, char __user *ubuf,
 	cnt = ring_buffer_read_events_cpu(trace_buf->buffer, cpu);
 	trace_seq_printf(s, "read events: %ld\n", cnt);
 
+	cnt = ring_buffer_writer_loops(trace_buf->buffer, cpu);
+	trace_seq_printf(s, "writer loops: %ld\n", cnt);
+
 	count = simple_read_from_buffer(ubuf, count, ppos,
 					s->buffer, trace_seq_used(s));
 
-- 
2.43.0
Keyboard shortcuts
hback out one level
jnext message in thread / next series-diff position
kprevious message in thread / previous series-diff position
ldrill in
Escclose help / fold thread tree
?toggle this help