Skip to content

Commit 20e7168

Browse files
mhiramatrostedt
authored andcommitted
tracing: Add boot-time backup of persistent ring buffer
Currently, the persistent ring buffer instance needs to be read before using it. This means we have to wait for boot up user space and dump the persistent ring buffer. However, in that case we can not start tracing on it from the kernel cmdline. To solve this limitation, this adds an option which allows to create a trace instance as a backup of the persistent ring buffer at boot. If user specifies trace_instance=<BACKUP>=<PERSIST_RB> then the <BACKUP> instance is made as a copy of the <PERSIST_RB> instance. For example, the below kernel cmdline records all syscalls, scheduler and interrupt events on the persistent ring buffer `boot_map` but before starting the tracing, it makes a `backup` instance from the `boot_map`. Thus, the `backup` instance has the previous boot events. 'reserve_mem=12M:4M:trace trace_instance=boot_map@trace,syscalls:*,sched:*,irq:* trace_instance=backup=boot_map' As you can see, this just make a copy of entire reserved area and make a backup instance on it. So you can release (or shrink) the backup instance after use it to save the memory usage. /sys/kernel/tracing/instances # free total used free shared buff/cache available Mem: 1999284 55704 1930520 10132 13060 1914628 Swap: 0 0 0 /sys/kernel/tracing/instances # rmdir backup/ /sys/kernel/tracing/instances # free total used free shared buff/cache available Mem: 1999284 40640 1945584 10132 13060 1929692 Swap: 0 0 0 Note: since there is no reason to make a copy of empty buffer, this backup only accepts a persistent ring buffer as the original instance. Also, since this backup is based on vmalloc(), it does not support user-space mmap(). Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Link: https://patch.msgid.link/176377150002.219692.9425536150438129267.stgit@devnote2 Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org> Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
1 parent f93a7d0 commit 20e7168

2 files changed

Lines changed: 58 additions & 6 deletions

File tree

kernel/trace/trace.c

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9004,8 +9004,8 @@ static int tracing_buffers_mmap(struct file *filp, struct vm_area_struct *vma)
90049004
struct trace_iterator *iter = &info->iter;
90059005
int ret = 0;
90069006

9007-
/* A memmap'ed buffer is not supported for user space mmap */
9008-
if (iter->tr->flags & TRACE_ARRAY_FL_MEMMAP)
9007+
/* A memmap'ed and backup buffers are not supported for user space mmap */
9008+
if (iter->tr->flags & (TRACE_ARRAY_FL_MEMMAP | TRACE_ARRAY_FL_VMALLOC))
90099009
return -ENODEV;
90109010

90119011
ret = get_snapshot_map(iter->tr);
@@ -10520,6 +10520,8 @@ static int __remove_instance(struct trace_array *tr)
1052010520
reserve_mem_release_by_name(tr->range_name);
1052110521
kfree(tr->range_name);
1052210522
}
10523+
if (tr->flags & TRACE_ARRAY_FL_VMALLOC)
10524+
vfree((void *)tr->range_addr_start);
1052310525

1052410526
for (i = 0; i < tr->nr_topts; i++) {
1052510527
kfree(tr->topts[i].topts);
@@ -11325,6 +11327,42 @@ __init static void do_allocate_snapshot(const char *name)
1132511327
static inline void do_allocate_snapshot(const char *name) { }
1132611328
#endif
1132711329

11330+
__init static int backup_instance_area(const char *backup,
11331+
unsigned long *addr, phys_addr_t *size)
11332+
{
11333+
struct trace_array *backup_tr;
11334+
void *allocated_vaddr = NULL;
11335+
11336+
backup_tr = trace_array_get_by_name(backup, NULL);
11337+
if (!backup_tr) {
11338+
pr_warn("Tracing: Instance %s is not found.\n", backup);
11339+
return -ENOENT;
11340+
}
11341+
11342+
if (!(backup_tr->flags & TRACE_ARRAY_FL_BOOT)) {
11343+
pr_warn("Tracing: Instance %s is not boot mapped.\n", backup);
11344+
trace_array_put(backup_tr);
11345+
return -EINVAL;
11346+
}
11347+
11348+
*size = backup_tr->range_addr_size;
11349+
11350+
allocated_vaddr = vzalloc(*size);
11351+
if (!allocated_vaddr) {
11352+
pr_warn("Tracing: Failed to allocate memory for copying instance %s (size 0x%lx)\n",
11353+
backup, (unsigned long)*size);
11354+
trace_array_put(backup_tr);
11355+
return -ENOMEM;
11356+
}
11357+
11358+
memcpy(allocated_vaddr,
11359+
(void *)backup_tr->range_addr_start, (size_t)*size);
11360+
*addr = (unsigned long)allocated_vaddr;
11361+
11362+
trace_array_put(backup_tr);
11363+
return 0;
11364+
}
11365+
1132811366
__init static void enable_instances(void)
1132911367
{
1133011368
struct trace_array *tr;
@@ -11347,19 +11385,26 @@ __init static void enable_instances(void)
1134711385
char *flag_delim;
1134811386
char *addr_delim;
1134911387
char *rname __free(kfree) = NULL;
11388+
char *backup;
1135011389

1135111390
tok = strsep(&curr_str, ",");
1135211391

11353-
flag_delim = strchr(tok, '^');
11354-
addr_delim = strchr(tok, '@');
11392+
name = strsep(&tok, "=");
11393+
backup = tok;
11394+
11395+
flag_delim = strchr(name, '^');
11396+
addr_delim = strchr(name, '@');
1135511397

1135611398
if (addr_delim)
1135711399
*addr_delim++ = '\0';
1135811400

1135911401
if (flag_delim)
1136011402
*flag_delim++ = '\0';
1136111403

11362-
name = tok;
11404+
if (backup) {
11405+
if (backup_instance_area(backup, &addr, &size) < 0)
11406+
continue;
11407+
}
1136311408

1136411409
if (flag_delim) {
1136511410
char *flag;
@@ -11455,7 +11500,13 @@ __init static void enable_instances(void)
1145511500
tr->ref++;
1145611501
}
1145711502

11458-
if (start) {
11503+
/*
11504+
* Backup buffers can be freed but need vfree().
11505+
*/
11506+
if (backup)
11507+
tr->flags |= TRACE_ARRAY_FL_VMALLOC;
11508+
11509+
if (start || backup) {
1145911510
tr->flags |= TRACE_ARRAY_FL_BOOT | TRACE_ARRAY_FL_LAST_BOOT;
1146011511
tr->range_name = no_free_ptr(rname);
1146111512
}

kernel/trace/trace.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,7 @@ enum {
454454
TRACE_ARRAY_FL_LAST_BOOT = BIT(2),
455455
TRACE_ARRAY_FL_MOD_INIT = BIT(3),
456456
TRACE_ARRAY_FL_MEMMAP = BIT(4),
457+
TRACE_ARRAY_FL_VMALLOC = BIT(5),
457458
};
458459

459460
#ifdef CONFIG_MODULES

0 commit comments

Comments
 (0)