[PATCH v2 4/4] ring-buffer: Record invalid buffer event
From: Masami Hiramatsu (Google)
Date: Wed Feb 18 2026 - 05:32:30 EST
From: Masami Hiramatsu (Google) <mhiramat@xxxxxxxxxx>
Record an invalid buffer event on the invalidated sub buffer
so that user can notice how much data is skipped.
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@xxxxxxxxxx>
---
kernel/trace/ring_buffer.c | 43 ++++++++++++++++++++++++++++++++++++------
kernel/trace/trace.h | 1 +
kernel/trace/trace_entries.h | 15 +++++++++++++++
3 files changed, 53 insertions(+), 6 deletions(-)
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 0ae2a5ad8c3e..98df5a67de26 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -1911,6 +1911,38 @@ static int rb_validate_buffer(struct buffer_data_page *dpage, int cpu)
return rb_read_data_buffer(dpage, tail, cpu, &ts, &delta);
}
+/* Inject invalid_buffer event */
+static void rb_record_invalid_buffer(struct buffer_page *buffer,
+ long commit_bytes, long entries,
+ int buffer_index)
+{
+ struct buffer_data_page *dpage = buffer->page;
+ struct invalid_subbuf_entry *entry;
+ struct ring_buffer_event *event;
+ long length;
+
+ length = DIV_ROUND_UP(sizeof(*entry), RB_ALIGNMENT);
+
+ /*
+ * Instead of ring_buffer_lock_reserve(), directly allocate it on
+ * the first entry of specific buffer_page.
+ */
+ event = (struct ring_buffer_event *)&dpage->data[0];
+ event->type_len = length;
+ event->time_delta = 0;
+
+ trace_event_setup(event, TRACE_INVALID_BUF, 0);
+
+ entry = ring_buffer_event_data(event);
+ entry->lost_bytes = commit_bytes;
+ entry->lost_entries = entries;
+ entry->buffer_index = buffer_index;
+
+ /* This buffer_page has only one event. */
+ local_set(&buffer->entries, 1);
+ local_set(&buffer->page->commit, rb_event_data_length(event));
+}
+
/* If the meta data has been validated, now validate the events */
static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer)
{
@@ -2043,12 +2075,11 @@ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer)
ret = rb_validate_buffer(head_page->page, cpu_buffer->cpu);
if (ret < 0) {
- pr_info("Ring buffer meta [%d] invalid buffer page\n",
- cpu_buffer->cpu);
- /* Instead of invalidate whole ring buffer, just clear this subbuffer. */
- local_set(&head_page->entries, 0);
- local_set(&head_page->page->commit, 0);
- /* TODO: commit an event to mark this is broken. */
+ /* Discard invalid buffer and record it. */
+ rb_record_invalid_buffer(head_page,
+ local_read(&head_page->page->commit),
+ local_read(&head_page->entries),
+ rb_meta_subbuf_idx(meta, head_page->page));
} else {
/* If the buffer has content, update pages_touched */
if (ret)
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 7894bf55743c..667834edb5b9 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -57,6 +57,7 @@ enum trace_type {
TRACE_TIMERLAT,
TRACE_RAW_DATA,
TRACE_FUNC_REPEATS,
+ TRACE_INVALID_BUF,
__TRACE_LAST_TYPE,
};
diff --git a/kernel/trace/trace_entries.h b/kernel/trace/trace_entries.h
index f6a8d29c0d76..df39fc245ab4 100644
--- a/kernel/trace/trace_entries.h
+++ b/kernel/trace/trace_entries.h
@@ -457,3 +457,18 @@ FTRACE_ENTRY(timerlat, timerlat_entry,
__entry->context,
__entry->timer_latency)
);
+
+FTRACE_ENTRY(invalid_subbuf, invalid_subbuf_entry,
+ TRACE_INVALID_BUF,
+
+ F_STRUCT(
+ __field( long, lost_bytes )
+ __field( long, lost_entries )
+ __field( int, buffer_index )
+ ),
+
+ F_printk("lost_bytes:%ld\tlost_entries:%ld\tbuffer_index:%d\n",
+ __entry->lost_bytes,
+ __entry->lost_entries,
+ __entry->buffer_index)
+);