ring-buffer: Do not die if rb_iter_peek() fails more than thrice

As the iterator will be reading a live buffer, and if the event being read
is on a page that a writer crosses, it will fail and try again, the
condition in rb_iter_peek() that only allows a retry to happen three times
is no longer valid. Allow rb_iter_peek() to retry more than three times
without killing the ring buffer, but only if rb_iter_head_event() had failed
at least once.

Link: http://lkml.kernel.org/r/20200317213416.452888193@goodmis.orgSigned-off-by: default avatarSteven Rostedt (VMware) <rostedt@goodmis.org>
parent 785888c5
...@@ -4012,6 +4012,7 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts) ...@@ -4012,6 +4012,7 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts)
struct ring_buffer_per_cpu *cpu_buffer; struct ring_buffer_per_cpu *cpu_buffer;
struct ring_buffer_event *event; struct ring_buffer_event *event;
int nr_loops = 0; int nr_loops = 0;
bool failed = false;
if (ts) if (ts)
*ts = 0; *ts = 0;
...@@ -4038,10 +4039,14 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts) ...@@ -4038,10 +4039,14 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts)
* to a data event, we should never loop more than three times. * to a data event, we should never loop more than three times.
* Once for going to next page, once on time extend, and * Once for going to next page, once on time extend, and
* finally once to get the event. * finally once to get the event.
* (We never hit the following condition more than thrice). * We should never hit the following condition more than thrice,
* unless the buffer is very small, and there's a writer
* that is causing the reader to fail getting an event.
*/ */
if (RB_WARN_ON(cpu_buffer, ++nr_loops > 3)) if (++nr_loops > 3) {
RB_WARN_ON(cpu_buffer, !failed);
return NULL; return NULL;
}
if (rb_per_cpu_empty(cpu_buffer)) if (rb_per_cpu_empty(cpu_buffer))
return NULL; return NULL;
...@@ -4052,8 +4057,10 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts) ...@@ -4052,8 +4057,10 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts)
} }
event = rb_iter_head_event(iter); event = rb_iter_head_event(iter);
if (!event) if (!event) {
failed = true;
goto again; goto again;
}
switch (event->type_len) { switch (event->type_len) {
case RINGBUF_TYPE_PADDING: case RINGBUF_TYPE_PADDING:
......
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