From: Masami Hiramatsu (Google) <[email protected]>

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) <[email protected]>
---
 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)
+);


Reply via email to