1
0
Fork 0

ring-buffer: discard timestamps that are at the start of the buffer

Every buffer page in the ring buffer includes its own time stamp.
When an event is recorded to the ring buffer with a delta time greater
than what can be held in the event header, a time stamp event is created.

If the the create timestamp falls over to the next buffer page, it is
redundant because the buffer page holds a full time stamp. This patch
will try to discard the time stamp when it falls to the start of the
next page.

This change also fixes a issues with disarding events. If most events are
discarded, timestamps will start to creep into the ring buffer. If we
do not discard the timestamps then they can fill up the ring buffer over
time and waste space.

This change will keep time stamps from filling up over another page. If
something is recorded in the buffer page, and the rest is filtered, then
the time stamps can only fill up to the end of the page.

[ Impact: prevent time stamps from filling ring buffer ]

Reported-by: Tim Bird <tim.bird@am.sony.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
hifive-unleashed-5.1
Steven Rostedt 2009-06-03 09:30:10 -04:00 committed by Steven Rostedt
parent edd813bffc
commit ea05b57cc1
1 changed files with 21 additions and 16 deletions

View File

@ -370,6 +370,9 @@ static inline int test_time_stamp(u64 delta)
/* Max payload is BUF_PAGE_SIZE - header (8bytes) */ /* Max payload is BUF_PAGE_SIZE - header (8bytes) */
#define BUF_MAX_DATA_SIZE (BUF_PAGE_SIZE - (sizeof(u32) * 2)) #define BUF_MAX_DATA_SIZE (BUF_PAGE_SIZE - (sizeof(u32) * 2))
/* Max number of timestamps that can fit on a page */
#define RB_TIMESTAMPS_PER_PAGE (BUF_PAGE_SIZE / RB_LEN_TIME_STAMP)
int ring_buffer_print_page_header(struct trace_seq *s) int ring_buffer_print_page_header(struct trace_seq *s)
{ {
struct buffer_data_page field; struct buffer_data_page field;
@ -1409,8 +1412,12 @@ rb_add_time_stamp(struct ring_buffer_per_cpu *cpu_buffer,
event->array[0] = *delta >> TS_SHIFT; event->array[0] = *delta >> TS_SHIFT;
} else { } else {
cpu_buffer->commit_page->page->time_stamp = *ts; cpu_buffer->commit_page->page->time_stamp = *ts;
event->time_delta = 0; /* try to discard, since we do not need this */
event->array[0] = 0; if (!rb_try_to_discard(cpu_buffer, event)) {
/* nope, just zero it */
event->time_delta = 0;
event->array[0] = 0;
}
} }
cpu_buffer->write_stamp = *ts; cpu_buffer->write_stamp = *ts;
/* let the caller know this was the commit */ /* let the caller know this was the commit */
@ -2268,8 +2275,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)) {
if (RB_WARN_ON(buffer, /* discarded commits can make the page empty */
iter->head_page == cpu_buffer->commit_page)) if (iter->head_page == cpu_buffer->commit_page)
return; return;
rb_inc_iter(iter); rb_inc_iter(iter);
return; return;
@ -2312,12 +2319,10 @@ rb_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts)
/* /*
* We repeat when a timestamp is encountered. It is possible * We repeat when a timestamp is encountered. It is possible
* to get multiple timestamps from an interrupt entering just * to get multiple timestamps from an interrupt entering just
* as one timestamp is about to be written. The max times * as one timestamp is about to be written, or from discarded
* that this can happen is the number of nested interrupts we * commits. The most that we can have is the number on a single page.
* can have. Nesting 10 deep of interrupts is clearly
* an anomaly.
*/ */
if (RB_WARN_ON(cpu_buffer, ++nr_loops > 10)) if (RB_WARN_ON(cpu_buffer, ++nr_loops > RB_TIMESTAMPS_PER_PAGE))
return NULL; return NULL;
reader = rb_get_reader_page(cpu_buffer); reader = rb_get_reader_page(cpu_buffer);
@ -2383,14 +2388,14 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts)
again: again:
/* /*
* We repeat when a timestamp is encountered. It is possible * We repeat when a timestamp is encountered.
* to get multiple timestamps from an interrupt entering just * We can get multiple timestamps by nested interrupts or also
* as one timestamp is about to be written. The max times * if filtering is on (discarding commits). Since discarding
* that this can happen is the number of nested interrupts we * commits can be frequent we can get a lot of timestamps.
* can have. Nesting 10 deep of interrupts is clearly * But we limit them by not adding timestamps if they begin
* an anomaly. * at the start of a page.
*/ */
if (RB_WARN_ON(cpu_buffer, ++nr_loops > 10)) if (RB_WARN_ON(cpu_buffer, ++nr_loops > RB_TIMESTAMPS_PER_PAGE))
return NULL; return NULL;
if (rb_per_cpu_empty(cpu_buffer)) if (rb_per_cpu_empty(cpu_buffer))