diff options
-rw-r--r-- | kernel/trace/ring_buffer.c | 49 |
1 files changed, 32 insertions, 17 deletions
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index bf27bb7a63e2..7c0168ad6d51 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c | |||
@@ -406,7 +406,7 @@ struct ring_buffer_per_cpu { | |||
406 | spinlock_t reader_lock; /* serialize readers */ | 406 | spinlock_t reader_lock; /* serialize readers */ |
407 | raw_spinlock_t lock; | 407 | raw_spinlock_t lock; |
408 | struct lock_class_key lock_key; | 408 | struct lock_class_key lock_key; |
409 | struct list_head pages; | 409 | struct list_head *pages; |
410 | struct buffer_page *head_page; /* read from head */ | 410 | struct buffer_page *head_page; /* read from head */ |
411 | struct buffer_page *tail_page; /* write to tail */ | 411 | struct buffer_page *tail_page; /* write to tail */ |
412 | struct buffer_page *commit_page; /* committed pages */ | 412 | struct buffer_page *commit_page; /* committed pages */ |
@@ -498,7 +498,7 @@ EXPORT_SYMBOL_GPL(ring_buffer_normalize_time_stamp); | |||
498 | */ | 498 | */ |
499 | static int rb_check_pages(struct ring_buffer_per_cpu *cpu_buffer) | 499 | static int rb_check_pages(struct ring_buffer_per_cpu *cpu_buffer) |
500 | { | 500 | { |
501 | struct list_head *head = &cpu_buffer->pages; | 501 | struct list_head *head = cpu_buffer->pages; |
502 | struct buffer_page *bpage, *tmp; | 502 | struct buffer_page *bpage, *tmp; |
503 | 503 | ||
504 | if (RB_WARN_ON(cpu_buffer, head->next->prev != head)) | 504 | if (RB_WARN_ON(cpu_buffer, head->next->prev != head)) |
@@ -521,12 +521,13 @@ static int rb_check_pages(struct ring_buffer_per_cpu *cpu_buffer) | |||
521 | static int rb_allocate_pages(struct ring_buffer_per_cpu *cpu_buffer, | 521 | static int rb_allocate_pages(struct ring_buffer_per_cpu *cpu_buffer, |
522 | unsigned nr_pages) | 522 | unsigned nr_pages) |
523 | { | 523 | { |
524 | struct list_head *head = &cpu_buffer->pages; | ||
525 | struct buffer_page *bpage, *tmp; | 524 | struct buffer_page *bpage, *tmp; |
526 | unsigned long addr; | 525 | unsigned long addr; |
527 | LIST_HEAD(pages); | 526 | LIST_HEAD(pages); |
528 | unsigned i; | 527 | unsigned i; |
529 | 528 | ||
529 | WARN_ON(!nr_pages); | ||
530 | |||
530 | for (i = 0; i < nr_pages; i++) { | 531 | for (i = 0; i < nr_pages; i++) { |
531 | bpage = kzalloc_node(ALIGN(sizeof(*bpage), cache_line_size()), | 532 | bpage = kzalloc_node(ALIGN(sizeof(*bpage), cache_line_size()), |
532 | GFP_KERNEL, cpu_to_node(cpu_buffer->cpu)); | 533 | GFP_KERNEL, cpu_to_node(cpu_buffer->cpu)); |
@@ -541,7 +542,13 @@ static int rb_allocate_pages(struct ring_buffer_per_cpu *cpu_buffer, | |||
541 | rb_init_page(bpage->page); | 542 | rb_init_page(bpage->page); |
542 | } | 543 | } |
543 | 544 | ||
544 | list_splice(&pages, head); | 545 | /* |
546 | * The ring buffer page list is a circular list that does not | ||
547 | * start and end with a list head. All page list items point to | ||
548 | * other pages. | ||
549 | */ | ||
550 | cpu_buffer->pages = pages.next; | ||
551 | list_del(&pages); | ||
545 | 552 | ||
546 | rb_check_pages(cpu_buffer); | 553 | rb_check_pages(cpu_buffer); |
547 | 554 | ||
@@ -573,7 +580,6 @@ rb_allocate_cpu_buffer(struct ring_buffer *buffer, int cpu) | |||
573 | spin_lock_init(&cpu_buffer->reader_lock); | 580 | spin_lock_init(&cpu_buffer->reader_lock); |
574 | lockdep_set_class(&cpu_buffer->reader_lock, buffer->reader_lock_key); | 581 | lockdep_set_class(&cpu_buffer->reader_lock, buffer->reader_lock_key); |
575 | cpu_buffer->lock = (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED; | 582 | cpu_buffer->lock = (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED; |
576 | INIT_LIST_HEAD(&cpu_buffer->pages); | ||
577 | 583 | ||
578 | bpage = kzalloc_node(ALIGN(sizeof(*bpage), cache_line_size()), | 584 | bpage = kzalloc_node(ALIGN(sizeof(*bpage), cache_line_size()), |
579 | GFP_KERNEL, cpu_to_node(cpu)); | 585 | GFP_KERNEL, cpu_to_node(cpu)); |
@@ -594,7 +600,7 @@ rb_allocate_cpu_buffer(struct ring_buffer *buffer, int cpu) | |||
594 | goto fail_free_reader; | 600 | goto fail_free_reader; |
595 | 601 | ||
596 | cpu_buffer->head_page | 602 | cpu_buffer->head_page |
597 | = list_entry(cpu_buffer->pages.next, struct buffer_page, list); | 603 | = list_entry(cpu_buffer->pages, struct buffer_page, list); |
598 | cpu_buffer->tail_page = cpu_buffer->commit_page = cpu_buffer->head_page; | 604 | cpu_buffer->tail_page = cpu_buffer->commit_page = cpu_buffer->head_page; |
599 | 605 | ||
600 | return cpu_buffer; | 606 | return cpu_buffer; |
@@ -609,15 +615,20 @@ rb_allocate_cpu_buffer(struct ring_buffer *buffer, int cpu) | |||
609 | 615 | ||
610 | static void rb_free_cpu_buffer(struct ring_buffer_per_cpu *cpu_buffer) | 616 | static void rb_free_cpu_buffer(struct ring_buffer_per_cpu *cpu_buffer) |
611 | { | 617 | { |
612 | struct list_head *head = &cpu_buffer->pages; | 618 | struct list_head *head = cpu_buffer->pages; |
613 | struct buffer_page *bpage, *tmp; | 619 | struct buffer_page *bpage, *tmp; |
614 | 620 | ||
615 | free_buffer_page(cpu_buffer->reader_page); | 621 | free_buffer_page(cpu_buffer->reader_page); |
616 | 622 | ||
617 | list_for_each_entry_safe(bpage, tmp, head, list) { | 623 | if (head) { |
618 | list_del_init(&bpage->list); | 624 | list_for_each_entry_safe(bpage, tmp, head, list) { |
625 | list_del_init(&bpage->list); | ||
626 | free_buffer_page(bpage); | ||
627 | } | ||
628 | bpage = list_entry(head, struct buffer_page, list); | ||
619 | free_buffer_page(bpage); | 629 | free_buffer_page(bpage); |
620 | } | 630 | } |
631 | |||
621 | kfree(cpu_buffer); | 632 | kfree(cpu_buffer); |
622 | } | 633 | } |
623 | 634 | ||
@@ -760,14 +771,14 @@ rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned nr_pages) | |||
760 | synchronize_sched(); | 771 | synchronize_sched(); |
761 | 772 | ||
762 | for (i = 0; i < nr_pages; i++) { | 773 | for (i = 0; i < nr_pages; i++) { |
763 | if (RB_WARN_ON(cpu_buffer, list_empty(&cpu_buffer->pages))) | 774 | if (RB_WARN_ON(cpu_buffer, list_empty(cpu_buffer->pages))) |
764 | return; | 775 | return; |
765 | p = cpu_buffer->pages.next; | 776 | p = cpu_buffer->pages->next; |
766 | bpage = list_entry(p, struct buffer_page, list); | 777 | bpage = list_entry(p, struct buffer_page, list); |
767 | list_del_init(&bpage->list); | 778 | list_del_init(&bpage->list); |
768 | free_buffer_page(bpage); | 779 | free_buffer_page(bpage); |
769 | } | 780 | } |
770 | if (RB_WARN_ON(cpu_buffer, list_empty(&cpu_buffer->pages))) | 781 | if (RB_WARN_ON(cpu_buffer, list_empty(cpu_buffer->pages))) |
771 | return; | 782 | return; |
772 | 783 | ||
773 | rb_reset_cpu(cpu_buffer); | 784 | rb_reset_cpu(cpu_buffer); |
@@ -795,7 +806,7 @@ rb_insert_pages(struct ring_buffer_per_cpu *cpu_buffer, | |||
795 | p = pages->next; | 806 | p = pages->next; |
796 | bpage = list_entry(p, struct buffer_page, list); | 807 | bpage = list_entry(p, struct buffer_page, list); |
797 | list_del_init(&bpage->list); | 808 | list_del_init(&bpage->list); |
798 | list_add_tail(&bpage->list, &cpu_buffer->pages); | 809 | list_add_tail(&bpage->list, cpu_buffer->pages); |
799 | } | 810 | } |
800 | rb_reset_cpu(cpu_buffer); | 811 | rb_reset_cpu(cpu_buffer); |
801 | 812 | ||
@@ -992,9 +1003,6 @@ static inline void rb_inc_page(struct ring_buffer_per_cpu *cpu_buffer, | |||
992 | { | 1003 | { |
993 | struct list_head *p = (*bpage)->list.next; | 1004 | struct list_head *p = (*bpage)->list.next; |
994 | 1005 | ||
995 | if (p == &cpu_buffer->pages) | ||
996 | p = p->next; | ||
997 | |||
998 | *bpage = list_entry(p, struct buffer_page, list); | 1006 | *bpage = list_entry(p, struct buffer_page, list); |
999 | } | 1007 | } |
1000 | 1008 | ||
@@ -2247,6 +2255,13 @@ rb_get_reader_page(struct ring_buffer_per_cpu *cpu_buffer) | |||
2247 | cpu_buffer->reader_page->list.next = reader->list.next; | 2255 | cpu_buffer->reader_page->list.next = reader->list.next; |
2248 | cpu_buffer->reader_page->list.prev = reader->list.prev; | 2256 | cpu_buffer->reader_page->list.prev = reader->list.prev; |
2249 | 2257 | ||
2258 | /* | ||
2259 | * cpu_buffer->pages just needs to point to the buffer, it | ||
2260 | * has no specific buffer page to point to. Lets move it out | ||
2261 | * of our way so we don't accidently swap it. | ||
2262 | */ | ||
2263 | cpu_buffer->pages = reader->list.prev; | ||
2264 | |||
2250 | local_set(&cpu_buffer->reader_page->write, 0); | 2265 | local_set(&cpu_buffer->reader_page->write, 0); |
2251 | local_set(&cpu_buffer->reader_page->entries, 0); | 2266 | local_set(&cpu_buffer->reader_page->entries, 0); |
2252 | local_set(&cpu_buffer->reader_page->page->commit, 0); | 2267 | local_set(&cpu_buffer->reader_page->page->commit, 0); |
@@ -2719,7 +2734,7 @@ static void | |||
2719 | rb_reset_cpu(struct ring_buffer_per_cpu *cpu_buffer) | 2734 | rb_reset_cpu(struct ring_buffer_per_cpu *cpu_buffer) |
2720 | { | 2735 | { |
2721 | cpu_buffer->head_page | 2736 | cpu_buffer->head_page |
2722 | = list_entry(cpu_buffer->pages.next, struct buffer_page, list); | 2737 | = list_entry(cpu_buffer->pages, struct buffer_page, list); |
2723 | local_set(&cpu_buffer->head_page->write, 0); | 2738 | local_set(&cpu_buffer->head_page->write, 0); |
2724 | local_set(&cpu_buffer->head_page->entries, 0); | 2739 | local_set(&cpu_buffer->head_page->entries, 0); |
2725 | local_set(&cpu_buffer->head_page->page->commit, 0); | 2740 | local_set(&cpu_buffer->head_page->page->commit, 0); |