aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-08-09 20:29:36 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-08-09 20:29:36 -0400
commitfc335c1b68c68f626f07f1819e57d112d666bbba (patch)
tree6718dbcf383cafc8d76b40ff2978eb72f480723e /kernel/trace
parent77e40aae766ccbbbb0324cb92ab22e6e998375d7 (diff)
parent651e22f2701b4113989237c3048d17337dd2185c (diff)
Merge tag 'trace-fixes-3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace
Pull trace file read iterator fixes from Steven Rostedt: "This contains a fix for two long standing bugs. Both of which are rarely ever hit, and requires the user to do something that users rarely do. It took a few special test cases to even trigger this bug, and one of them was just one test in the process of finishing up as another one started. Both bugs have to do with the ring buffer iterator rb_iter_peek(), but one is more indirect than the other. The fist bug fix is simply an increase in the safety net loop counter. The counter makes sure that the rb_iter_peek() only iterates the number of times we expect it can, and no more. Well, there was one way it could iterate one more than we expected, and that caused the ring buffer to shutdown with a nasty warning. The fix was simply to up that counter by one. The other bug has to be with rb_iter_reset() (called by rb_iter_peek()). This happens when a user reads both the trace_pipe and trace files. The trace_pipe is a consuming read and does not use the ring buffer iterator, but the trace file is not a consuming read and does use the ring buffer iterator. When the trace file is being read, if it detects that a consuming read occurred, it resets the iterator and starts over. But the reset code that does this (rb_iter_reset()), checks if the reader_page is linked to the ring buffer or not, and will look into the ring buffer itself if it is not. This is wrong, as it should always try to read the reader page first. Not to mention, the code that looked into the ring buffer did it wrong, and used the header_page "read" offset to start reading on that page. That offset is bogus for pages in the writable ring buffer, and was corrupting the iterator, and it would start returning bogus events" * tag 'trace-fixes-3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace: ring-buffer: Always reset iterator to reader page ring-buffer: Up rb_iter_peek() loop count to 3
Diffstat (limited to 'kernel/trace')
-rw-r--r--kernel/trace/ring_buffer.c31
1 files changed, 14 insertions, 17 deletions
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 925f629658d6..afb04b9b818a 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -1968,7 +1968,7 @@ rb_add_time_stamp(struct ring_buffer_event *event, u64 delta)
1968 1968
1969/** 1969/**
1970 * rb_update_event - update event type and data 1970 * rb_update_event - update event type and data
1971 * @event: the even to update 1971 * @event: the event to update
1972 * @type: the type of event 1972 * @type: the type of event
1973 * @length: the size of the event field in the ring buffer 1973 * @length: the size of the event field in the ring buffer
1974 * 1974 *
@@ -3341,21 +3341,16 @@ static void rb_iter_reset(struct ring_buffer_iter *iter)
3341 struct ring_buffer_per_cpu *cpu_buffer = iter->cpu_buffer; 3341 struct ring_buffer_per_cpu *cpu_buffer = iter->cpu_buffer;
3342 3342
3343 /* Iterator usage is expected to have record disabled */ 3343 /* Iterator usage is expected to have record disabled */
3344 if (list_empty(&cpu_buffer->reader_page->list)) { 3344 iter->head_page = cpu_buffer->reader_page;
3345 iter->head_page = rb_set_head_page(cpu_buffer); 3345 iter->head = cpu_buffer->reader_page->read;
3346 if (unlikely(!iter->head_page)) 3346
3347 return; 3347 iter->cache_reader_page = iter->head_page;
3348 iter->head = iter->head_page->read; 3348 iter->cache_read = iter->head;
3349 } else { 3349
3350 iter->head_page = cpu_buffer->reader_page;
3351 iter->head = cpu_buffer->reader_page->read;
3352 }
3353 if (iter->head) 3350 if (iter->head)
3354 iter->read_stamp = cpu_buffer->read_stamp; 3351 iter->read_stamp = cpu_buffer->read_stamp;
3355 else 3352 else
3356 iter->read_stamp = iter->head_page->page->time_stamp; 3353 iter->read_stamp = iter->head_page->page->time_stamp;
3357 iter->cache_reader_page = cpu_buffer->reader_page;
3358 iter->cache_read = cpu_buffer->read;
3359} 3354}
3360 3355
3361/** 3356/**
@@ -3748,12 +3743,14 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts)
3748 return NULL; 3743 return NULL;
3749 3744
3750 /* 3745 /*
3751 * We repeat when a time extend is encountered. 3746 * We repeat when a time extend is encountered or we hit
3752 * Since the time extend is always attached to a data event, 3747 * the end of the page. Since the time extend is always attached
3753 * we should never loop more than once. 3748 * to a data event, we should never loop more than three times.
3754 * (We never hit the following condition more than twice). 3749 * Once for going to next page, once on time extend, and
3750 * finally once to get the event.
3751 * (We never hit the following condition more than thrice).
3755 */ 3752 */
3756 if (RB_WARN_ON(cpu_buffer, ++nr_loops > 2)) 3753 if (RB_WARN_ON(cpu_buffer, ++nr_loops > 3))
3757 return NULL; 3754 return NULL;
3758 3755
3759 if (rb_per_cpu_empty(cpu_buffer)) 3756 if (rb_per_cpu_empty(cpu_buffer))