mirror of https://gitee.com/openkylin/linux.git
ring-buffer: fix ring_buffer_read crossing pages
When the ring buffer uses an iterator (static read mode, not on the fly reading), when it crosses a page boundery, it will skip the first entry on the next page. The reason is that the last entry of a page is usually padding if the page is not full. The padding will not be returned to the user. The problem arises on ring_buffer_read because it also increments the iterator. Because both the read and peek use the same rb_iter_peek, the rb_iter_peak will return the padding but also increment to the next item. This is because the ring_buffer_peek will not incerment it itself. The ring_buffer_read will increment it again and then call rb_iter_peek again to get the next item. But that will be the second item, not the first one on the page. The reason this never showed up before, is because the ftrace utility always calls ring_buffer_peek first and only uses ring_buffer_read to increment to the next item. The ring_buffer_peek will always keep the pointer to a valid item and not padding. This just hid the bug. Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
This commit is contained in:
parent
1b959e18c4
commit
7e9391cfed
|
@ -3286,19 +3286,19 @@ ring_buffer_read(struct ring_buffer_iter *iter, u64 *ts)
|
||||||
struct ring_buffer_per_cpu *cpu_buffer = iter->cpu_buffer;
|
struct ring_buffer_per_cpu *cpu_buffer = iter->cpu_buffer;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
again:
|
|
||||||
spin_lock_irqsave(&cpu_buffer->reader_lock, flags);
|
spin_lock_irqsave(&cpu_buffer->reader_lock, flags);
|
||||||
|
again:
|
||||||
event = rb_iter_peek(iter, ts);
|
event = rb_iter_peek(iter, ts);
|
||||||
if (!event)
|
if (!event)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
if (event->type_len == RINGBUF_TYPE_PADDING)
|
||||||
|
goto again;
|
||||||
|
|
||||||
rb_advance_iter(iter);
|
rb_advance_iter(iter);
|
||||||
out:
|
out:
|
||||||
spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags);
|
spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags);
|
||||||
|
|
||||||
if (event && event->type_len == RINGBUF_TYPE_PADDING)
|
|
||||||
goto again;
|
|
||||||
|
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(ring_buffer_read);
|
EXPORT_SYMBOL_GPL(ring_buffer_read);
|
||||||
|
|
Loading…
Reference in New Issue