lkml.org 
[lkml]   [2010]   [Dec]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH] ring_buffer: off-by-one and duplicate events in ring_buffer_read_page
    Date
    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>
    CC: Steven Rostedt <rostedt@goodmis.net>
    LKML-Reference: <AANLkTin7nLrRPc9qGjdjHbeVDDWiJjAiYyb-L=gH85bx@mail.gmail.com>
    ---
    kernel/trace/ring_buffer.c | 9 ++++++++-
    1 files changed, 8 insertions(+), 1 deletions(-)

    diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
    index 9ed509a..bd1c35a 100644
    --- a/kernel/trace/ring_buffer.c
    +++ b/kernel/trace/ring_buffer.c
    @@ -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);
    --
    1.7.3.1


    \
     
     \ /
      Last update: 2010-12-23 00:49    [W:0.021 / U:1.528 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site