]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
ring-buffer: Fix infinite spin in reading buffer
authorSteven Rostedt (Red Hat) <rostedt@goodmis.org>
Thu, 2 Oct 2014 20:51:18 +0000 (16:51 -0400)
committerSteven Rostedt <rostedt@goodmis.org>
Thu, 2 Oct 2014 20:51:18 +0000 (16:51 -0400)
Commit 651e22f2701b "ring-buffer: Always reset iterator to reader page"
fixed one bug but in the process caused another one. The reset is to
update the header page, but that fix also changed the way the cached
reads were updated. The cache reads are used to test if an iterator
needs to be updated or not.

A ring buffer iterator, when created, disables writes to the ring buffer
but does not stop other readers or consuming reads from happening.
Although all readers are synchronized via a lock, they are only
synchronized when in the ring buffer functions. Those functions may
be called by any number of readers. The iterator continues down when
its not interrupted by a consuming reader. If a consuming read
occurs, the iterator starts from the beginning of the buffer.

The way the iterator sees that a consuming read has happened since
its last read is by checking the reader "cache". The cache holds the
last counts of the read and the reader page itself.

Commit 651e22f2701b changed what was saved by the cache_read when
the rb_iter_reset() occurred, making the iterator never match the cache.
Then if the iterator calls rb_iter_reset(), it will go into an
infinite loop by checking if the cache doesn't match, doing the reset
and retrying, just to see that the cache still doesn't match! Which
should never happen as the reset is suppose to set the cache to the
current value and there's locks that keep a consuming reader from
having access to the data.

Fixes: 651e22f2701b "ring-buffer: Always reset iterator to reader page"
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
kernel/trace/ring_buffer.c

index b38fb2b9e23772d3f3360ef556cf0714d4a44803..2d75c94ae87d871bbf42db7b1ee949463bb7f65f 100644 (file)
@@ -3359,7 +3359,7 @@ static void rb_iter_reset(struct ring_buffer_iter *iter)
        iter->head = cpu_buffer->reader_page->read;
 
        iter->cache_reader_page = iter->head_page;
-       iter->cache_read = iter->head;
+       iter->cache_read = cpu_buffer->read;
 
        if (iter->head)
                iter->read_stamp = cpu_buffer->read_stamp;