| From 78f7a45dac2a2d2002f98a3a95f7979867868d73 Mon Sep 17 00:00:00 2001 |
| From: "Steven Rostedt (VMware)" <rostedt@goodmis.org> |
| Date: Wed, 19 Apr 2017 14:29:46 -0400 |
| Subject: [PATCH] ring-buffer: Have ring_buffer_iter_empty() return true when |
| empty |
| |
| commit 78f7a45dac2a2d2002f98a3a95f7979867868d73 upstream. |
| |
| I noticed that reading the snapshot file when it is empty no longer gives a |
| status. It suppose to show the status of the snapshot buffer as well as how |
| to allocate and use it. For example: |
| |
| ># cat snapshot |
| # tracer: nop |
| # |
| # |
| # * Snapshot is allocated * |
| # |
| # Snapshot commands: |
| # echo 0 > snapshot : Clears and frees snapshot buffer |
| # echo 1 > snapshot : Allocates snapshot buffer, if not already allocated. |
| # Takes a snapshot of the main buffer. |
| # echo 2 > snapshot : Clears snapshot buffer (but does not allocate or free) |
| # (Doesn't have to be '2' works with any number that |
| # is not a '0' or '1') |
| |
| But instead it just showed an empty buffer: |
| |
| ># cat snapshot |
| # tracer: nop |
| # |
| # entries-in-buffer/entries-written: 0/0 #P:4 |
| # |
| # _-----=> irqs-off |
| # / _----=> need-resched |
| # | / _---=> hardirq/softirq |
| # || / _--=> preempt-depth |
| # ||| / delay |
| # TASK-PID CPU# |||| TIMESTAMP FUNCTION |
| # | | | |||| | | |
| |
| What happened was that it was using the ring_buffer_iter_empty() function to |
| see if it was empty, and if it was, it showed the status. But that function |
| was returning false when it was empty. The reason was that the iter header |
| page was on the reader page, and the reader page was empty, but so was the |
| buffer itself. The check only tested to see if the iter was on the commit |
| page, but the commit page was no longer pointing to the reader page, but as |
| all pages were empty, the buffer is also. |
| |
| Cc: stable@vger.kernel.org |
| Fixes: 651e22f2701b ("ring-buffer: Always reset iterator to reader page") |
| Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org> |
| |
| diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c |
| index 54e7a90db848..ca47a4fa2986 100644 |
| --- a/kernel/trace/ring_buffer.c |
| +++ b/kernel/trace/ring_buffer.c |
| @@ -3405,11 +3405,23 @@ EXPORT_SYMBOL_GPL(ring_buffer_iter_reset); |
| int ring_buffer_iter_empty(struct ring_buffer_iter *iter) |
| { |
| struct ring_buffer_per_cpu *cpu_buffer; |
| + struct buffer_page *reader; |
| + struct buffer_page *head_page; |
| + struct buffer_page *commit_page; |
| + unsigned commit; |
| |
| cpu_buffer = iter->cpu_buffer; |
| |
| - return iter->head_page == cpu_buffer->commit_page && |
| - iter->head == rb_commit_index(cpu_buffer); |
| + /* Remember, trace recording is off when iterator is in use */ |
| + reader = cpu_buffer->reader_page; |
| + head_page = cpu_buffer->head_page; |
| + commit_page = cpu_buffer->commit_page; |
| + commit = rb_page_commit(commit_page); |
| + |
| + return ((iter->head_page == commit_page && iter->head == commit) || |
| + (iter->head_page == reader && commit_page == head_page && |
| + head_page->read == commit && |
| + iter->head == rb_page_commit(cpu_buffer->reader_page))); |
| } |
| EXPORT_SYMBOL_GPL(ring_buffer_iter_empty); |
| |
| -- |
| 2.12.0 |
| |