Messages in this thread Patch in this message | | | From | David Sharp <> | Subject | [PATCH] ring-buffer: fix uninitialized read_stamp | Date | Mon, 18 Jun 2012 16:02:57 -0700 |
| |
This fixes a scenario in which trace_pipe_raw will return events with invalid timestamps when events are copied out one at a time (instead of swapping out the reader page with a spare page). In this scenario, ring_buffer_read_page() uses cpu_buffer->read_stamp to keep track of the time of the earliest event. However, cpu_buffer->read_stamp was not always updated. The only function that sets read_stamp to a new valid value is rb_reset_reader_page(), which is called only by rb_get_reader_page(). rb_reset_reader_page() was not called when there is data immediately available on the page to read (read < rb_page_size()). This is the bug.
Setting the read_stamp on the first read from a page fixes the bug.
Tested: On certain lightly-loaded machines, repetitive reads from trace_pipe_raw without using splice() would sometimes result in invalid timestamps. Poisoning bpage->timestamp in rb_init_page() with a negative value makes the problem more visible. After this fix, the invalid timstamps disappear.
Google-Bug-Id: 6410455 Signed-off-by: David Sharp <dhsharp@google.com> ---
Steve, did you see this? It fixes a data-accuracy bug in ftrace. Also taking this reminder as an opportunity to correct that typo in the description.
kernel/trace/ring_buffer.c | 9 ++++++++- 1 files changed, 8 insertions(+), 1 deletions(-)
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 1d0f6a8..ad0239b 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -3226,8 +3226,15 @@ rb_get_reader_page(struct ring_buffer_per_cpu *cpu_buffer) reader = cpu_buffer->reader_page; /* If there's more to read, return this page */ - if (cpu_buffer->reader_page->read < rb_page_size(reader)) + if (cpu_buffer->reader_page->read < rb_page_size(reader)) { + /* + * If this is the first read from this page, + * initialize the read timestamp. + */ + if (cpu_buffer->reader_page->read == 0) + cpu_buffer->read_stamp = reader->page->time_stamp; goto out; + } /* Never should we have an index greater than the size */ if (RB_WARN_ON(cpu_buffer, -- 1.7.7.3
| |