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

Skip invalid sub-buffers when validating the persistent ring buffer
instead of discarding the entire ring buffer. Also, mark there are
missed events on the discarded buffer.

If the cache data in memory fails to be synchronized during a reboot,
the persistent ring buffer may become partially corrupted, but other
sub-buffers may still contain readable event data. Only discard the
subbuffersa that ar found to be corrupted.

Signed-off-by: Masami Hiramatsu (Google) <[email protected]>
---
  Changes in v5:
  - Instead of showing errors for each page, just show the number
    of discarded pages at last.
  Changes in v3:
  - Record missed data event on commit.
---
 kernel/trace/ring_buffer.c |   28 +++++++++++++++-------------
 1 file changed, 15 insertions(+), 13 deletions(-)

diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 2e9b8ce6b4dc..cfe1e15f1a93 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -1927,6 +1927,7 @@ static void rb_meta_validate_events(struct 
ring_buffer_per_cpu *cpu_buffer)
        struct buffer_page *head_page, *orig_head;
        unsigned long entry_bytes = 0;
        unsigned long entries = 0;
+       int discarded = 0;
        int ret;
        u64 ts;
        int i;
@@ -2053,19 +2054,19 @@ 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);
-                       goto invalid;
-               }
-
-               /* If the buffer has content, update pages_touched */
-               if (ret)
-                       local_inc(&cpu_buffer->pages_touched);
-
-               entries += ret;
-               entry_bytes += rb_page_size(head_page);
-               local_set(&cpu_buffer->head_page->entries, ret);
+                       discarded++;
+                       /* Instead of discard whole ring buffer, discard only 
this sub-buffer. */
+                       local_set(&head_page->entries, 0);
+                       local_set(&head_page->page->commit, RB_MISSED_EVENTS);
+               } else {
+                       /* If the buffer has content, update pages_touched */
+                       if (ret)
+                               local_inc(&cpu_buffer->pages_touched);
 
+                       entries += ret;
+                       entry_bytes += rb_page_size(head_page);
+                       local_set(&cpu_buffer->head_page->entries, ret);
+               }
                if (head_page == cpu_buffer->commit_page)
                        break;
        }
@@ -2079,7 +2080,8 @@ static void rb_meta_validate_events(struct 
ring_buffer_per_cpu *cpu_buffer)
        local_set(&cpu_buffer->entries, entries);
        local_set(&cpu_buffer->entries_bytes, entry_bytes);
 
-       pr_info("Ring buffer meta [%d] is from previous boot!\n", 
cpu_buffer->cpu);
+       pr_info("Ring buffer meta [%d] is from previous boot! (%d pages 
discarded)\n",
+               cpu_buffer->cpu, discarded);
        return;
 
  invalid:


Reply via email to