Skip to content

Commit f50345b

Browse files
committed
ring-buffer: Check if absolute timestamp goes backwards
The check_buffer() which checks the timestamps of the ring buffer sub-buffer page, when enabled, only checks if the adding of deltas of the events from the last absolute timestamp or the timestamp of the sub-buffer page adds up to the current event. What it does not check is if the absolute timestamp causes the time of the events to go backwards, as that can cause issues elsewhere. Test for the timestamp going backwards too. This also fixes a slight issue where if the warning triggers at boot up (because of the resetting of the tsc), it will disable all further checks, even those that are after boot Have it continue checking if the warning was ignored during boot up. Link: https://lore.kernel.org/linux-trace-kernel/[email protected] Cc: Masami Hiramatsu <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Mathieu Desnoyers <[email protected]> Signed-off-by: Steven Rostedt (Google) <[email protected]>
1 parent d40dbb6 commit f50345b

File tree

1 file changed

+28
-18
lines changed

1 file changed

+28
-18
lines changed

kernel/trace/ring_buffer.c

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3309,6 +3309,23 @@ static void dump_buffer_page(struct buffer_data_page *bpage,
33093309
static DEFINE_PER_CPU(atomic_t, checking);
33103310
static atomic_t ts_dump;
33113311

3312+
#define buffer_warn_return(fmt, ...) \
3313+
do { \
3314+
/* If another report is happening, ignore this one */ \
3315+
if (atomic_inc_return(&ts_dump) != 1) { \
3316+
atomic_dec(&ts_dump); \
3317+
goto out; \
3318+
} \
3319+
atomic_inc(&cpu_buffer->record_disabled); \
3320+
pr_warn(fmt, ##__VA_ARGS__); \
3321+
dump_buffer_page(bpage, info, tail); \
3322+
atomic_dec(&ts_dump); \
3323+
/* There's some cases in boot up that this can happen */ \
3324+
if (WARN_ON_ONCE(system_state != SYSTEM_BOOTING)) \
3325+
/* Do not re-enable checking */ \
3326+
return; \
3327+
} while (0)
3328+
33123329
/*
33133330
* Check if the current event time stamp matches the deltas on
33143331
* the buffer page.
@@ -3362,7 +3379,12 @@ static void check_buffer(struct ring_buffer_per_cpu *cpu_buffer,
33623379

33633380
case RINGBUF_TYPE_TIME_STAMP:
33643381
delta = rb_event_time_stamp(event);
3365-
ts = rb_fix_abs_ts(delta, ts);
3382+
delta = rb_fix_abs_ts(delta, ts);
3383+
if (delta < ts) {
3384+
buffer_warn_return("[CPU: %d]ABSOLUTE TIME WENT BACKWARDS: last ts: %lld absolute ts: %lld\n",
3385+
cpu_buffer->cpu, ts, delta);
3386+
}
3387+
ts = delta;
33663388
break;
33673389

33683390
case RINGBUF_TYPE_PADDING:
@@ -3379,23 +3401,11 @@ static void check_buffer(struct ring_buffer_per_cpu *cpu_buffer,
33793401
}
33803402
if ((full && ts > info->ts) ||
33813403
(!full && ts + info->delta != info->ts)) {
3382-
/* If another report is happening, ignore this one */
3383-
if (atomic_inc_return(&ts_dump) != 1) {
3384-
atomic_dec(&ts_dump);
3385-
goto out;
3386-
}
3387-
atomic_inc(&cpu_buffer->record_disabled);
3388-
/* There's some cases in boot up that this can happen */
3389-
WARN_ON_ONCE(system_state != SYSTEM_BOOTING);
3390-
pr_warn("[CPU: %d]TIME DOES NOT MATCH expected:%lld actual:%lld delta:%lld before:%lld after:%lld%s context:%s\n",
3391-
cpu_buffer->cpu,
3392-
ts + info->delta, info->ts, info->delta,
3393-
info->before, info->after,
3394-
full ? " (full)" : "", show_interrupt_level());
3395-
dump_buffer_page(bpage, info, tail);
3396-
atomic_dec(&ts_dump);
3397-
/* Do not re-enable checking */
3398-
return;
3404+
buffer_warn_return("[CPU: %d]TIME DOES NOT MATCH expected:%lld actual:%lld delta:%lld before:%lld after:%lld%s context:%s\n",
3405+
cpu_buffer->cpu,
3406+
ts + info->delta, info->ts, info->delta,
3407+
info->before, info->after,
3408+
full ? " (full)" : "", show_interrupt_level());
33993409
}
34003410
out:
34013411
atomic_dec(this_cpu_ptr(&checking));

0 commit comments

Comments
 (0)