Skip to content

Commit

Permalink
ring-buffer: fix dangling commit race
Browse files Browse the repository at this point in the history
Impact: fix stuck trace-buffers

If an interrupt comes in during the rb_set_commit_to_write and
pushes the tail page forward just at the right time, the commit
updates will miss the adding of the interrupt data. This will
cause the commit pointer to cease from moving forward.

Thanks to Jiaying Zhang for finding this race.

Reported-by: Jiaying Zhang <[email protected]>
Signed-off-by: Steven Rostedt <[email protected]>
Cc: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
  • Loading branch information
Steven Rostedt authored and Ingo Molnar committed Dec 23, 2008
1 parent 30cd324 commit a8ccf1d
Showing 1 changed file with 12 additions and 0 deletions.
12 changes: 12 additions & 0 deletions kernel/trace/ring_buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,7 @@ rb_set_commit_to_write(struct ring_buffer_per_cpu *cpu_buffer)
* back to us). This allows us to do a simple loop to
* assign the commit to the tail.
*/
again:
while (cpu_buffer->commit_page != cpu_buffer->tail_page) {
cpu_buffer->commit_page->page->commit =
cpu_buffer->commit_page->write;
Expand All @@ -853,6 +854,17 @@ rb_set_commit_to_write(struct ring_buffer_per_cpu *cpu_buffer)
cpu_buffer->commit_page->write;
barrier();
}

/* again, keep gcc from optimizing */
barrier();

/*
* If an interrupt came in just after the first while loop
* and pushed the tail page forward, we will be left with
* a dangling commit that will never go forward.
*/
if (unlikely(cpu_buffer->commit_page != cpu_buffer->tail_page))
goto again;
}

static void rb_reset_reader_page(struct ring_buffer_per_cpu *cpu_buffer)
Expand Down

0 comments on commit a8ccf1d

Please sign in to comment.