mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-23 20:24:12 +08:00
ring_buffer: Off-by-one and duplicate events in ring_buffer_read_page
Fix two related problems in the event-copying loop of ring_buffer_read_page. The loop condition for copying events is off-by-one. "len" is the remaining space in the caller-supplied page. "size" is the size of the next event (or two events). If len == size, then there is just enough space for the next event. size was set to rb_event_ts_length, which may include the size of two events if the first event is a time-extend, in order to assure time- extends are kept together with the event after it. However, rb_advance_reader always advances by one event. This would result in the event after any time-extend being duplicated. Instead, get the size of a single event for the memcpy, but use rb_event_ts_length for the loop condition. Signed-off-by: David Sharp <dhsharp@google.com> LKML-Reference: <1293064704-8101-1-git-send-email-dhsharp@google.com> LKML-Reference: <AANLkTin7nLrRPc9qGjdjHbeVDDWiJjAiYyb-L=gH85bx@mail.gmail.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
This commit is contained in:
parent
2ce494a3da
commit
e1e3592735
@ -3853,6 +3853,13 @@ int ring_buffer_read_page(struct ring_buffer *buffer,
|
||||
|
||||
/* Need to copy one event at a time */
|
||||
do {
|
||||
/* We need the size of one event, because
|
||||
* rb_advance_reader only advances by one event,
|
||||
* whereas rb_event_ts_length may include the size of
|
||||
* one or two events.
|
||||
* We have already ensured there's enough space if this
|
||||
* is a time extend. */
|
||||
size = rb_event_length(event);
|
||||
memcpy(bpage->data + pos, rpage->data + rpos, size);
|
||||
|
||||
len -= size;
|
||||
@ -3867,7 +3874,7 @@ int ring_buffer_read_page(struct ring_buffer *buffer,
|
||||
event = rb_reader_event(cpu_buffer);
|
||||
/* Always keep the time extend and data together */
|
||||
size = rb_event_ts_length(event);
|
||||
} while (len > size);
|
||||
} while (len >= size);
|
||||
|
||||
/* update bpage */
|
||||
local_set(&bpage->commit, pos);
|
||||
|
Loading…
Reference in New Issue
Block a user