Commit f536aafc authored by Steven Rostedt's avatar Steven Rostedt Committed by Ingo Molnar

ring-buffer: replace most bug ons with warn on and disable buffer

This patch replaces most of the BUG_ONs in the ring_buffer code with
RB_WARN_ON variants. It adds some more variants as needed for the
replacement. This lets the buffer die nicely and still warn the user.

One BUG_ON remains in the code, and that is because it detects a
bad pointer passed in by the calling function, and not a bug by
the ring buffer code itself.
Signed-off-by: default avatarSteven Rostedt <srostedt@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 5aa1ba6a
...@@ -188,6 +188,7 @@ struct ring_buffer_iter { ...@@ -188,6 +188,7 @@ struct ring_buffer_iter {
u64 read_stamp; u64 read_stamp;
}; };
/* buffer may be either ring_buffer or ring_buffer_per_cpu */
#define RB_WARN_ON(buffer, cond) \ #define RB_WARN_ON(buffer, cond) \
do { \ do { \
if (unlikely(cond)) { \ if (unlikely(cond)) { \
...@@ -197,6 +198,15 @@ struct ring_buffer_iter { ...@@ -197,6 +198,15 @@ struct ring_buffer_iter {
} while (0) } while (0)
#define RB_WARN_ON_RET(buffer, cond) \ #define RB_WARN_ON_RET(buffer, cond) \
do { \
if (unlikely(cond)) { \
atomic_inc(&buffer->record_disabled); \
WARN_ON(1); \
return; \
} \
} while (0)
#define RB_WARN_ON_RET_INT(buffer, cond) \
do { \ do { \
if (unlikely(cond)) { \ if (unlikely(cond)) { \
atomic_inc(&buffer->record_disabled); \ atomic_inc(&buffer->record_disabled); \
...@@ -205,6 +215,15 @@ struct ring_buffer_iter { ...@@ -205,6 +215,15 @@ struct ring_buffer_iter {
} \ } \
} while (0) } while (0)
#define RB_WARN_ON_RET_NULL(buffer, cond) \
do { \
if (unlikely(cond)) { \
atomic_inc(&buffer->record_disabled); \
WARN_ON(1); \
return NULL; \
} \
} while (0)
#define RB_WARN_ON_ONCE(buffer, cond) \ #define RB_WARN_ON_ONCE(buffer, cond) \
do { \ do { \
static int once; \ static int once; \
...@@ -215,6 +234,17 @@ struct ring_buffer_iter { ...@@ -215,6 +234,17 @@ struct ring_buffer_iter {
} \ } \
} while (0) } while (0)
/* buffer must be ring_buffer not per_cpu */
#define RB_WARN_ON_UNLOCK(buffer, cond) \
do { \
if (unlikely(cond)) { \
mutex_unlock(&buffer->mutex); \
atomic_inc(&buffer->record_disabled); \
WARN_ON(1); \
return -1; \
} \
} while (0)
/** /**
* check_pages - integrity check of buffer pages * check_pages - integrity check of buffer pages
* @cpu_buffer: CPU buffer with pages to test * @cpu_buffer: CPU buffer with pages to test
...@@ -227,13 +257,13 @@ static int rb_check_pages(struct ring_buffer_per_cpu *cpu_buffer) ...@@ -227,13 +257,13 @@ static int rb_check_pages(struct ring_buffer_per_cpu *cpu_buffer)
struct list_head *head = &cpu_buffer->pages; struct list_head *head = &cpu_buffer->pages;
struct buffer_page *page, *tmp; struct buffer_page *page, *tmp;
RB_WARN_ON_RET(cpu_buffer, head->next->prev != head); RB_WARN_ON_RET_INT(cpu_buffer, head->next->prev != head);
RB_WARN_ON_RET(cpu_buffer, head->prev->next != head); RB_WARN_ON_RET_INT(cpu_buffer, head->prev->next != head);
list_for_each_entry_safe(page, tmp, head, list) { list_for_each_entry_safe(page, tmp, head, list) {
RB_WARN_ON_RET(cpu_buffer, RB_WARN_ON_RET_INT(cpu_buffer,
page->list.next->prev != &page->list); page->list.next->prev != &page->list);
RB_WARN_ON_RET(cpu_buffer, RB_WARN_ON_RET_INT(cpu_buffer,
page->list.prev->next != &page->list); page->list.prev->next != &page->list);
} }
...@@ -440,13 +470,13 @@ rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned nr_pages) ...@@ -440,13 +470,13 @@ rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned nr_pages)
synchronize_sched(); synchronize_sched();
for (i = 0; i < nr_pages; i++) { for (i = 0; i < nr_pages; i++) {
BUG_ON(list_empty(&cpu_buffer->pages)); RB_WARN_ON_RET(cpu_buffer, list_empty(&cpu_buffer->pages));
p = cpu_buffer->pages.next; p = cpu_buffer->pages.next;
page = list_entry(p, struct buffer_page, list); page = list_entry(p, struct buffer_page, list);
list_del_init(&page->list); list_del_init(&page->list);
free_buffer_page(page); free_buffer_page(page);
} }
BUG_ON(list_empty(&cpu_buffer->pages)); RB_WARN_ON_RET(cpu_buffer, list_empty(&cpu_buffer->pages));
rb_reset_cpu(cpu_buffer); rb_reset_cpu(cpu_buffer);
...@@ -468,7 +498,7 @@ rb_insert_pages(struct ring_buffer_per_cpu *cpu_buffer, ...@@ -468,7 +498,7 @@ rb_insert_pages(struct ring_buffer_per_cpu *cpu_buffer,
synchronize_sched(); synchronize_sched();
for (i = 0; i < nr_pages; i++) { for (i = 0; i < nr_pages; i++) {
BUG_ON(list_empty(pages)); RB_WARN_ON_RET(cpu_buffer, list_empty(pages));
p = pages->next; p = pages->next;
page = list_entry(p, struct buffer_page, list); page = list_entry(p, struct buffer_page, list);
list_del_init(&page->list); list_del_init(&page->list);
...@@ -523,7 +553,7 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size) ...@@ -523,7 +553,7 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size)
if (size < buffer_size) { if (size < buffer_size) {
/* easy case, just free pages */ /* easy case, just free pages */
BUG_ON(nr_pages >= buffer->pages); RB_WARN_ON_UNLOCK(buffer, nr_pages >= buffer->pages);
rm_pages = buffer->pages - nr_pages; rm_pages = buffer->pages - nr_pages;
...@@ -542,7 +572,8 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size) ...@@ -542,7 +572,8 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size)
* add these pages to the cpu_buffers. Otherwise we just free * add these pages to the cpu_buffers. Otherwise we just free
* them all and return -ENOMEM; * them all and return -ENOMEM;
*/ */
BUG_ON(nr_pages <= buffer->pages); RB_WARN_ON_UNLOCK(buffer, nr_pages <= buffer->pages);
new_pages = nr_pages - buffer->pages; new_pages = nr_pages - buffer->pages;
for_each_buffer_cpu(buffer, cpu) { for_each_buffer_cpu(buffer, cpu) {
...@@ -565,7 +596,7 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size) ...@@ -565,7 +596,7 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size)
rb_insert_pages(cpu_buffer, &pages, new_pages); rb_insert_pages(cpu_buffer, &pages, new_pages);
} }
BUG_ON(!list_empty(&pages)); RB_WARN_ON_UNLOCK(buffer, !list_empty(&pages));
out: out:
buffer->pages = nr_pages; buffer->pages = nr_pages;
...@@ -653,7 +684,7 @@ static void rb_update_overflow(struct ring_buffer_per_cpu *cpu_buffer) ...@@ -653,7 +684,7 @@ static void rb_update_overflow(struct ring_buffer_per_cpu *cpu_buffer)
head += rb_event_length(event)) { head += rb_event_length(event)) {
event = __rb_page_index(cpu_buffer->head_page, head); event = __rb_page_index(cpu_buffer->head_page, head);
BUG_ON(rb_null_event(event)); RB_WARN_ON_RET(cpu_buffer, rb_null_event(event));
/* Only count data entries */ /* Only count data entries */
if (event->type != RINGBUF_TYPE_DATA) if (event->type != RINGBUF_TYPE_DATA)
continue; continue;
...@@ -940,7 +971,7 @@ __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer, ...@@ -940,7 +971,7 @@ __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer,
/* We reserved something on the buffer */ /* We reserved something on the buffer */
BUG_ON(write > BUF_PAGE_SIZE); RB_WARN_ON_RET_NULL(cpu_buffer, write > BUF_PAGE_SIZE);
event = __rb_page_index(tail_page, tail); event = __rb_page_index(tail_page, tail);
rb_update_event(event, type, length); rb_update_event(event, type, length);
...@@ -1621,7 +1652,7 @@ static void rb_advance_reader(struct ring_buffer_per_cpu *cpu_buffer) ...@@ -1621,7 +1652,7 @@ static void rb_advance_reader(struct ring_buffer_per_cpu *cpu_buffer)
reader = rb_get_reader_page(cpu_buffer); reader = rb_get_reader_page(cpu_buffer);
/* This function should not be called when buffer is empty */ /* This function should not be called when buffer is empty */
BUG_ON(!reader); RB_WARN_ON_RET(cpu_buffer, !reader);
event = rb_reader_event(cpu_buffer); event = rb_reader_event(cpu_buffer);
...@@ -1648,7 +1679,8 @@ static void rb_advance_iter(struct ring_buffer_iter *iter) ...@@ -1648,7 +1679,8 @@ static void rb_advance_iter(struct ring_buffer_iter *iter)
* Check if we are at the end of the buffer. * Check if we are at the end of the buffer.
*/ */
if (iter->head >= rb_page_size(iter->head_page)) { if (iter->head >= rb_page_size(iter->head_page)) {
BUG_ON(iter->head_page == cpu_buffer->commit_page); RB_WARN_ON_RET(buffer,
iter->head_page == cpu_buffer->commit_page);
rb_inc_iter(iter); rb_inc_iter(iter);
return; return;
} }
...@@ -1661,8 +1693,9 @@ static void rb_advance_iter(struct ring_buffer_iter *iter) ...@@ -1661,8 +1693,9 @@ static void rb_advance_iter(struct ring_buffer_iter *iter)
* This should not be called to advance the header if we are * This should not be called to advance the header if we are
* at the tail of the buffer. * at the tail of the buffer.
*/ */
BUG_ON((iter->head_page == cpu_buffer->commit_page) && RB_WARN_ON_RET(cpu_buffer,
(iter->head + length > rb_commit_index(cpu_buffer))); (iter->head_page == cpu_buffer->commit_page) &&
(iter->head + length > rb_commit_index(cpu_buffer)));
rb_update_iter_read_stamp(iter, event); rb_update_iter_read_stamp(iter, event);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment