diff options
Diffstat (limited to 'kernel/trace/ring_buffer.c')
-rw-r--r-- | kernel/trace/ring_buffer.c | 37 |
1 files changed, 33 insertions, 4 deletions
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 8295650444c5..dc6d563a6d22 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c | |||
@@ -320,6 +320,8 @@ EXPORT_SYMBOL_GPL(ring_buffer_event_data); | |||
320 | 320 | ||
321 | /* Flag when events were overwritten */ | 321 | /* Flag when events were overwritten */ |
322 | #define RB_MISSED_EVENTS (1 << 31) | 322 | #define RB_MISSED_EVENTS (1 << 31) |
323 | /* Missed count stored at end */ | ||
324 | #define RB_MISSED_STORED (1 << 30) | ||
323 | 325 | ||
324 | struct buffer_data_page { | 326 | struct buffer_data_page { |
325 | u64 time_stamp; /* page time stamp */ | 327 | u64 time_stamp; /* page time stamp */ |
@@ -340,6 +342,7 @@ struct buffer_page { | |||
340 | local_t write; /* index for next write */ | 342 | local_t write; /* index for next write */ |
341 | unsigned read; /* index for next read */ | 343 | unsigned read; /* index for next read */ |
342 | local_t entries; /* entries on this page */ | 344 | local_t entries; /* entries on this page */ |
345 | unsigned long real_end; /* real end of data */ | ||
343 | struct buffer_data_page *page; /* Actual data page */ | 346 | struct buffer_data_page *page; /* Actual data page */ |
344 | }; | 347 | }; |
345 | 348 | ||
@@ -1770,6 +1773,13 @@ rb_reset_tail(struct ring_buffer_per_cpu *cpu_buffer, | |||
1770 | kmemcheck_annotate_bitfield(event, bitfield); | 1773 | kmemcheck_annotate_bitfield(event, bitfield); |
1771 | 1774 | ||
1772 | /* | 1775 | /* |
1776 | * Save the original length to the meta data. | ||
1777 | * This will be used by the reader to add lost event | ||
1778 | * counter. | ||
1779 | */ | ||
1780 | tail_page->real_end = tail; | ||
1781 | |||
1782 | /* | ||
1773 | * If this event is bigger than the minimum size, then | 1783 | * If this event is bigger than the minimum size, then |
1774 | * we need to be careful that we don't subtract the | 1784 | * we need to be careful that we don't subtract the |
1775 | * write counter enough to allow another writer to slip | 1785 | * write counter enough to allow another writer to slip |
@@ -2888,6 +2898,7 @@ rb_get_reader_page(struct ring_buffer_per_cpu *cpu_buffer) | |||
2888 | local_set(&cpu_buffer->reader_page->write, 0); | 2898 | local_set(&cpu_buffer->reader_page->write, 0); |
2889 | local_set(&cpu_buffer->reader_page->entries, 0); | 2899 | local_set(&cpu_buffer->reader_page->entries, 0); |
2890 | local_set(&cpu_buffer->reader_page->page->commit, 0); | 2900 | local_set(&cpu_buffer->reader_page->page->commit, 0); |
2901 | cpu_buffer->reader_page->real_end = 0; | ||
2891 | 2902 | ||
2892 | spin: | 2903 | spin: |
2893 | /* | 2904 | /* |
@@ -3728,11 +3739,11 @@ int ring_buffer_read_page(struct ring_buffer *buffer, | |||
3728 | struct ring_buffer_event *event; | 3739 | struct ring_buffer_event *event; |
3729 | struct buffer_data_page *bpage; | 3740 | struct buffer_data_page *bpage; |
3730 | struct buffer_page *reader; | 3741 | struct buffer_page *reader; |
3742 | unsigned long missed_events; | ||
3731 | unsigned long flags; | 3743 | unsigned long flags; |
3732 | unsigned int commit; | 3744 | unsigned int commit; |
3733 | unsigned int read; | 3745 | unsigned int read; |
3734 | u64 save_timestamp; | 3746 | u64 save_timestamp; |
3735 | int missed_events = 0; | ||
3736 | int ret = -1; | 3747 | int ret = -1; |
3737 | 3748 | ||
3738 | if (!cpumask_test_cpu(cpu, buffer->cpumask)) | 3749 | if (!cpumask_test_cpu(cpu, buffer->cpumask)) |
@@ -3766,8 +3777,7 @@ int ring_buffer_read_page(struct ring_buffer *buffer, | |||
3766 | commit = rb_page_commit(reader); | 3777 | commit = rb_page_commit(reader); |
3767 | 3778 | ||
3768 | /* Check if any events were dropped */ | 3779 | /* Check if any events were dropped */ |
3769 | if (cpu_buffer->lost_events) | 3780 | missed_events = cpu_buffer->lost_events; |
3770 | missed_events = 1; | ||
3771 | 3781 | ||
3772 | /* | 3782 | /* |
3773 | * If this page has been partially read or | 3783 | * If this page has been partially read or |
@@ -3829,6 +3839,14 @@ int ring_buffer_read_page(struct ring_buffer *buffer, | |||
3829 | local_set(&reader->entries, 0); | 3839 | local_set(&reader->entries, 0); |
3830 | reader->read = 0; | 3840 | reader->read = 0; |
3831 | *data_page = bpage; | 3841 | *data_page = bpage; |
3842 | |||
3843 | /* | ||
3844 | * Use the real_end for the data size, | ||
3845 | * This gives us a chance to store the lost events | ||
3846 | * on the page. | ||
3847 | */ | ||
3848 | if (reader->real_end) | ||
3849 | local_set(&bpage->commit, reader->real_end); | ||
3832 | } | 3850 | } |
3833 | ret = read; | 3851 | ret = read; |
3834 | 3852 | ||
@@ -3836,8 +3854,19 @@ int ring_buffer_read_page(struct ring_buffer *buffer, | |||
3836 | /* | 3854 | /* |
3837 | * Set a flag in the commit field if we lost events | 3855 | * Set a flag in the commit field if we lost events |
3838 | */ | 3856 | */ |
3839 | if (missed_events) | 3857 | if (missed_events) { |
3858 | commit = local_read(&bpage->commit); | ||
3859 | |||
3860 | /* If there is room at the end of the page to save the | ||
3861 | * missed events, then record it there. | ||
3862 | */ | ||
3863 | if (BUF_PAGE_SIZE - commit >= sizeof(missed_events)) { | ||
3864 | memcpy(&bpage->data[commit], &missed_events, | ||
3865 | sizeof(missed_events)); | ||
3866 | local_add(RB_MISSED_STORED, &bpage->commit); | ||
3867 | } | ||
3840 | local_add(RB_MISSED_EVENTS, &bpage->commit); | 3868 | local_add(RB_MISSED_EVENTS, &bpage->commit); |
3869 | } | ||
3841 | 3870 | ||
3842 | out_unlock: | 3871 | out_unlock: |
3843 | spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); | 3872 | spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); |