diff options
Diffstat (limited to 'kernel/trace/ring_buffer.c')
| -rw-r--r-- | kernel/trace/ring_buffer.c | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index edefe3b2801b..0287f9f52f5a 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/cpu.h> | 20 | #include <linux/cpu.h> |
| 21 | #include <linux/fs.h> | 21 | #include <linux/fs.h> |
| 22 | 22 | ||
| 23 | #include <asm/local.h> | ||
| 23 | #include "trace.h" | 24 | #include "trace.h" |
| 24 | 25 | ||
| 25 | /* | 26 | /* |
| @@ -464,6 +465,8 @@ struct ring_buffer_iter { | |||
| 464 | struct ring_buffer_per_cpu *cpu_buffer; | 465 | struct ring_buffer_per_cpu *cpu_buffer; |
| 465 | unsigned long head; | 466 | unsigned long head; |
| 466 | struct buffer_page *head_page; | 467 | struct buffer_page *head_page; |
| 468 | struct buffer_page *cache_reader_page; | ||
| 469 | unsigned long cache_read; | ||
| 467 | u64 read_stamp; | 470 | u64 read_stamp; |
| 468 | }; | 471 | }; |
| 469 | 472 | ||
| @@ -2716,6 +2719,8 @@ static void rb_iter_reset(struct ring_buffer_iter *iter) | |||
| 2716 | iter->read_stamp = cpu_buffer->read_stamp; | 2719 | iter->read_stamp = cpu_buffer->read_stamp; |
| 2717 | else | 2720 | else |
| 2718 | iter->read_stamp = iter->head_page->page->time_stamp; | 2721 | iter->read_stamp = iter->head_page->page->time_stamp; |
| 2722 | iter->cache_reader_page = cpu_buffer->reader_page; | ||
| 2723 | iter->cache_read = cpu_buffer->read; | ||
| 2719 | } | 2724 | } |
| 2720 | 2725 | ||
| 2721 | /** | 2726 | /** |
| @@ -3060,13 +3065,22 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts) | |||
| 3060 | struct ring_buffer_event *event; | 3065 | struct ring_buffer_event *event; |
| 3061 | int nr_loops = 0; | 3066 | int nr_loops = 0; |
| 3062 | 3067 | ||
| 3063 | if (ring_buffer_iter_empty(iter)) | ||
| 3064 | return NULL; | ||
| 3065 | |||
| 3066 | cpu_buffer = iter->cpu_buffer; | 3068 | cpu_buffer = iter->cpu_buffer; |
| 3067 | buffer = cpu_buffer->buffer; | 3069 | buffer = cpu_buffer->buffer; |
| 3068 | 3070 | ||
| 3071 | /* | ||
| 3072 | * Check if someone performed a consuming read to | ||
| 3073 | * the buffer. A consuming read invalidates the iterator | ||
| 3074 | * and we need to reset the iterator in this case. | ||
| 3075 | */ | ||
| 3076 | if (unlikely(iter->cache_read != cpu_buffer->read || | ||
| 3077 | iter->cache_reader_page != cpu_buffer->reader_page)) | ||
| 3078 | rb_iter_reset(iter); | ||
| 3079 | |||
| 3069 | again: | 3080 | again: |
| 3081 | if (ring_buffer_iter_empty(iter)) | ||
| 3082 | return NULL; | ||
| 3083 | |||
| 3070 | /* | 3084 | /* |
| 3071 | * We repeat when a timestamp is encountered. | 3085 | * We repeat when a timestamp is encountered. |
| 3072 | * We can get multiple timestamps by nested interrupts or also | 3086 | * We can get multiple timestamps by nested interrupts or also |
| @@ -3081,6 +3095,11 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts) | |||
| 3081 | if (rb_per_cpu_empty(cpu_buffer)) | 3095 | if (rb_per_cpu_empty(cpu_buffer)) |
| 3082 | return NULL; | 3096 | return NULL; |
| 3083 | 3097 | ||
| 3098 | if (iter->head >= local_read(&iter->head_page->page->commit)) { | ||
| 3099 | rb_inc_iter(iter); | ||
| 3100 | goto again; | ||
| 3101 | } | ||
| 3102 | |||
| 3084 | event = rb_iter_head_event(iter); | 3103 | event = rb_iter_head_event(iter); |
| 3085 | 3104 | ||
| 3086 | switch (event->type_len) { | 3105 | switch (event->type_len) { |
