From: "Steven Rostedt (Google)" <rost...@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) <rost...@goodmis.org> --- [ Depends on: https://lore.kernel.org/linux-trace-kernel/20240118181206.4977d...@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