Skip to content

Commit 7a1d1e4

Browse files
committed
tracing/ring-buffer: Add last_boot_info file to boot instance
If an instance is mapped to memory on boot up, create a new file called "last_boot_info" that will hold information that can be used to properly parse the raw data in the ring buffer. It will export the delta of the addresses for text and data from what it was from the last boot. It does not expose actually addresses (unless you knew what the actual address was from the last boot). The output will look like: # cat last_boot_info text delta: -268435456 data delta: -268435456 The text and data are kept separate in case they are ever made different. Link: https://lkml.kernel.org/r/[email protected] Cc: Masami Hiramatsu <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Mathieu Desnoyers <[email protected]> Cc: Andrew Morton <[email protected]> Cc: Vincent Donnefort <[email protected]> Cc: Joel Fernandes <[email protected]> Cc: Daniel Bristot de Oliveira <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Vineeth Pillai <[email protected]> Cc: Youssef Esmat <[email protected]> Cc: Beau Belgrave <[email protected]> Cc: Alexander Graf <[email protected]> Cc: Baoquan He <[email protected]> Cc: Borislav Petkov <[email protected]> Cc: "Paul E. McKenney" <[email protected]> Cc: David Howells <[email protected]> Cc: Mike Rapoport <[email protected]> Cc: Dave Hansen <[email protected]> Cc: Tony Luck <[email protected]> Cc: Guenter Roeck <[email protected]> Cc: Ross Zwisler <[email protected]> Cc: Kees Cook <[email protected]> Signed-off-by: Steven Rostedt (Google) <[email protected]>
1 parent 8f3e665 commit 7a1d1e4

File tree

4 files changed

+74
-1
lines changed

4 files changed

+74
-1
lines changed

include/linux/ring_buffer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ struct trace_buffer *__ring_buffer_alloc_range(unsigned long size, unsigned flag
9494
unsigned long range_size,
9595
struct lock_class_key *key);
9696

97+
bool ring_buffer_last_boot_delta(struct trace_buffer *buffer, long *text,
98+
long *data);
99+
97100
/*
98101
* Because the ring buffer is generic, if other users of the ring buffer get
99102
* traced by ftrace, it can produce lockdep warnings. We need to keep each

kernel/trace/ring_buffer.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2396,6 +2396,29 @@ struct trace_buffer *__ring_buffer_alloc_range(unsigned long size, unsigned flag
23962396
return alloc_buffer(size, flags, order, start, start + range_size, key);
23972397
}
23982398

2399+
/**
2400+
* ring_buffer_last_boot_delta - return the delta offset from last boot
2401+
* @buffer: The buffer to return the delta from
2402+
* @text: Return text delta
2403+
* @data: Return data delta
2404+
*
2405+
* Returns: The true if the delta is non zero
2406+
*/
2407+
bool ring_buffer_last_boot_delta(struct trace_buffer *buffer, long *text,
2408+
long *data)
2409+
{
2410+
if (!buffer)
2411+
return false;
2412+
2413+
if (!buffer->last_text_delta)
2414+
return false;
2415+
2416+
*text = buffer->last_text_delta;
2417+
*data = buffer->last_data_delta;
2418+
2419+
return true;
2420+
}
2421+
23992422
/**
24002423
* ring_buffer_free - free a ring buffer.
24012424
* @buffer: the buffer to free.

kernel/trace/trace.c

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6041,6 +6041,18 @@ ssize_t tracing_resize_ring_buffer(struct trace_array *tr,
60416041
return ret;
60426042
}
60436043

6044+
static void update_last_data(struct trace_array *tr)
6045+
{
6046+
if (!tr->text_delta && !tr->data_delta)
6047+
return;
6048+
6049+
/* Clear old data */
6050+
tracing_reset_online_cpus(&tr->array_buffer);
6051+
6052+
/* Using current data now */
6053+
tr->text_delta = 0;
6054+
tr->data_delta = 0;
6055+
}
60446056

60456057
/**
60466058
* tracing_update_buffers - used by tracing facility to expand ring buffers
@@ -6058,6 +6070,9 @@ int tracing_update_buffers(struct trace_array *tr)
60586070
int ret = 0;
60596071

60606072
mutex_lock(&trace_types_lock);
6073+
6074+
update_last_data(tr);
6075+
60616076
if (!tr->ring_buffer_expanded)
60626077
ret = __tracing_resize_ring_buffer(tr, trace_buf_size,
60636078
RING_BUFFER_ALL_CPUS);
@@ -6113,6 +6128,8 @@ int tracing_set_tracer(struct trace_array *tr, const char *buf)
61136128

61146129
mutex_lock(&trace_types_lock);
61156130

6131+
update_last_data(tr);
6132+
61166133
if (!tr->ring_buffer_expanded) {
61176134
ret = __tracing_resize_ring_buffer(tr, trace_buf_size,
61186135
RING_BUFFER_ALL_CPUS);
@@ -6860,6 +6877,21 @@ tracing_total_entries_read(struct file *filp, char __user *ubuf,
68606877
return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
68616878
}
68626879

6880+
static ssize_t
6881+
tracing_last_boot_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
6882+
{
6883+
struct trace_array *tr = filp->private_data;
6884+
struct seq_buf seq;
6885+
char buf[64];
6886+
6887+
seq_buf_init(&seq, buf, 64);
6888+
6889+
seq_buf_printf(&seq, "text delta:\t%ld\n", tr->text_delta);
6890+
seq_buf_printf(&seq, "data delta:\t%ld\n", tr->data_delta);
6891+
6892+
return simple_read_from_buffer(ubuf, cnt, ppos, buf, seq_buf_used(&seq));
6893+
}
6894+
68636895
static int tracing_buffer_meta_open(struct inode *inode, struct file *filp)
68646896
{
68656897
struct trace_array *tr = inode->i_private;
@@ -7499,6 +7531,13 @@ static const struct file_operations trace_time_stamp_mode_fops = {
74997531
.release = tracing_single_release_tr,
75007532
};
75017533

7534+
static const struct file_operations last_boot_fops = {
7535+
.open = tracing_open_generic_tr,
7536+
.read = tracing_last_boot_read,
7537+
.llseek = generic_file_llseek,
7538+
.release = tracing_release_generic_tr,
7539+
};
7540+
75027541
#ifdef CONFIG_TRACER_SNAPSHOT
75037542
static const struct file_operations snapshot_fops = {
75047543
.open = tracing_snapshot_open,
@@ -9242,6 +9281,9 @@ allocate_trace_buffer(struct trace_array *tr, struct array_buffer *buf, int size
92429281
buf->buffer = ring_buffer_alloc_range(size, rb_flags, 0,
92439282
tr->range_addr_start,
92449283
tr->range_addr_size);
9284+
9285+
ring_buffer_last_boot_delta(buf->buffer,
9286+
&tr->text_delta, &tr->data_delta);
92459287
/*
92469288
* This is basically the same as a mapped buffer,
92479289
* with the same restrictions.
@@ -9751,7 +9793,10 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer)
97519793
MEM_FAIL(1, "Could not allocate function filter files");
97529794

97539795
#ifdef CONFIG_TRACER_SNAPSHOT
9754-
if (!tr->range_addr_start) {
9796+
if (tr->range_addr_start) {
9797+
trace_create_file("last_boot_info", TRACE_MODE_READ, d_tracer,
9798+
tr, &last_boot_fops);
9799+
} else {
97559800
trace_create_file("snapshot", TRACE_MODE_WRITE, d_tracer,
97569801
tr, &snapshot_fops);
97579802
}

kernel/trace/trace.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,8 @@ struct trace_array {
347347
unsigned int mapped;
348348
unsigned long range_addr_start;
349349
unsigned long range_addr_size;
350+
long text_delta;
351+
long data_delta;
350352

351353
struct trace_pid_list __rcu *filtered_pids;
352354
struct trace_pid_list __rcu *filtered_no_pids;

0 commit comments

Comments
 (0)