Commit fc335c1b authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'trace-fixes-3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace

Pull trace file read iterator fixes from Steven Rostedt:
 "This contains a fix for two long standing bugs.  Both of which are
  rarely ever hit, and requires the user to do something that users
  rarely do.  It took a few special test cases to even trigger this bug,
  and one of them was just one test in the process of finishing up as
  another one started.

  Both bugs have to do with the ring buffer iterator rb_iter_peek(), but
  one is more indirect than the other.

  The fist bug fix is simply an increase in the safety net loop counter.
  The counter makes sure that the rb_iter_peek() only iterates the
  number of times we expect it can, and no more.  Well, there was one
  way it could iterate one more than we expected, and that caused the
  ring buffer to shutdown with a nasty warning.  The fix was simply to
  up that counter by one.

  The other bug has to be with rb_iter_reset() (called by
  rb_iter_peek()).  This happens when a user reads both the trace_pipe
  and trace files.  The trace_pipe is a consuming read and does not use
  the ring buffer iterator, but the trace file is not a consuming read
  and does use the ring buffer iterator.  When the trace file is being
  read, if it detects that a consuming read occurred, it resets the
  iterator and starts over.  But the reset code that does this
  (rb_iter_reset()), checks if the reader_page is linked to the ring
  buffer or not, and will look into the ring buffer itself if it is not.
  This is wrong, as it should always try to read the reader page first.
  Not to mention, the code that looked into the ring buffer did it
  wrong, and used the header_page "read" offset to start reading on that
  page.  That offset is bogus for pages in the writable ring buffer, and
  was corrupting the iterator, and it would start returning bogus
  events"

* tag 'trace-fixes-3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace:
  ring-buffer: Always reset iterator to reader page
  ring-buffer: Up rb_iter_peek() loop count to 3
parents 77e40aae 651e22f2
...@@ -1968,7 +1968,7 @@ rb_add_time_stamp(struct ring_buffer_event *event, u64 delta) ...@@ -1968,7 +1968,7 @@ rb_add_time_stamp(struct ring_buffer_event *event, u64 delta)
/** /**
* rb_update_event - update event type and data * rb_update_event - update event type and data
* @event: the even to update * @event: the event to update
* @type: the type of event * @type: the type of event
* @length: the size of the event field in the ring buffer * @length: the size of the event field in the ring buffer
* *
...@@ -3341,21 +3341,16 @@ static void rb_iter_reset(struct ring_buffer_iter *iter) ...@@ -3341,21 +3341,16 @@ static void rb_iter_reset(struct ring_buffer_iter *iter)
struct ring_buffer_per_cpu *cpu_buffer = iter->cpu_buffer; struct ring_buffer_per_cpu *cpu_buffer = iter->cpu_buffer;
/* Iterator usage is expected to have record disabled */ /* Iterator usage is expected to have record disabled */
if (list_empty(&cpu_buffer->reader_page->list)) {
iter->head_page = rb_set_head_page(cpu_buffer);
if (unlikely(!iter->head_page))
return;
iter->head = iter->head_page->read;
} else {
iter->head_page = cpu_buffer->reader_page; iter->head_page = cpu_buffer->reader_page;
iter->head = cpu_buffer->reader_page->read; iter->head = cpu_buffer->reader_page->read;
}
iter->cache_reader_page = iter->head_page;
iter->cache_read = iter->head;
if (iter->head) if (iter->head)
iter->read_stamp = cpu_buffer->read_stamp; iter->read_stamp = cpu_buffer->read_stamp;
else else
iter->read_stamp = iter->head_page->page->time_stamp; iter->read_stamp = iter->head_page->page->time_stamp;
iter->cache_reader_page = cpu_buffer->reader_page;
iter->cache_read = cpu_buffer->read;
} }
/** /**
...@@ -3748,12 +3743,14 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts) ...@@ -3748,12 +3743,14 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts)
return NULL; return NULL;
/* /*
* We repeat when a time extend is encountered. * We repeat when a time extend is encountered or we hit
* Since the time extend is always attached to a data event, * the end of the page. Since the time extend is always attached
* we should never loop more than once. * to a data event, we should never loop more than three times.
* (We never hit the following condition more than twice). * Once for going to next page, once on time extend, and
*/ * finally once to get the event.
if (RB_WARN_ON(cpu_buffer, ++nr_loops > 2)) * (We never hit the following condition more than thrice).
*/
if (RB_WARN_ON(cpu_buffer, ++nr_loops > 3))
return NULL; return NULL;
if (rb_per_cpu_empty(cpu_buffer)) if (rb_per_cpu_empty(cpu_buffer))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment