Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Masami Hiramatsu (Google) and committed by
Steven Rostedt (Google)
20e71683 f93a7d0c

+58 -6
+57 -6
kernel/trace/trace.c
··· 9004 9004 struct trace_iterator *iter = &info->iter; 9005 9005 int ret = 0; 9006 9006 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)) 9009 9009 return -ENODEV; 9010 9010 9011 9011 ret = get_snapshot_map(iter->tr); ··· 10520 10520 reserve_mem_release_by_name(tr->range_name); 10521 10521 kfree(tr->range_name); 10522 10522 } 10523 + if (tr->flags & TRACE_ARRAY_FL_VMALLOC) 10524 + vfree((void *)tr->range_addr_start); 10523 10525 10524 10526 for (i = 0; i < tr->nr_topts; i++) { 10525 10527 kfree(tr->topts[i].topts); ··· 11327 11325 static inline void do_allocate_snapshot(const char *name) { } 11328 11326 #endif 11329 11327 11328 + __init static int backup_instance_area(const char *backup, 11329 + unsigned long *addr, phys_addr_t *size) 11330 + { 11331 + struct trace_array *backup_tr; 11332 + void *allocated_vaddr = NULL; 11333 + 11334 + backup_tr = trace_array_get_by_name(backup, NULL); 11335 + if (!backup_tr) { 11336 + pr_warn("Tracing: Instance %s is not found.\n", backup); 11337 + return -ENOENT; 11338 + } 11339 + 11340 + if (!(backup_tr->flags & TRACE_ARRAY_FL_BOOT)) { 11341 + pr_warn("Tracing: Instance %s is not boot mapped.\n", backup); 11342 + trace_array_put(backup_tr); 11343 + return -EINVAL; 11344 + } 11345 + 11346 + *size = backup_tr->range_addr_size; 11347 + 11348 + allocated_vaddr = vzalloc(*size); 11349 + if (!allocated_vaddr) { 11350 + pr_warn("Tracing: Failed to allocate memory for copying instance %s (size 0x%lx)\n", 11351 + backup, (unsigned long)*size); 11352 + trace_array_put(backup_tr); 11353 + return -ENOMEM; 11354 + } 11355 + 11356 + memcpy(allocated_vaddr, 11357 + (void *)backup_tr->range_addr_start, (size_t)*size); 11358 + *addr = (unsigned long)allocated_vaddr; 11359 + 11360 + trace_array_put(backup_tr); 11361 + return 0; 11362 + } 11363 + 11330 11364 __init static void enable_instances(void) 11331 11365 { 11332 11366 struct trace_array *tr; ··· 11385 11347 char *flag_delim; 11386 11348 char *addr_delim; 11387 11349 char *rname __free(kfree) = NULL; 11350 + char *backup; 11388 11351 11389 11352 tok = strsep(&curr_str, ","); 11390 11353 11391 - flag_delim = strchr(tok, '^'); 11392 - addr_delim = strchr(tok, '@'); 11354 + name = strsep(&tok, "="); 11355 + backup = tok; 11356 + 11357 + flag_delim = strchr(name, '^'); 11358 + addr_delim = strchr(name, '@'); 11393 11359 11394 11360 if (addr_delim) 11395 11361 *addr_delim++ = '\0'; ··· 11401 11359 if (flag_delim) 11402 11360 *flag_delim++ = '\0'; 11403 11361 11404 - name = tok; 11362 + if (backup) { 11363 + if (backup_instance_area(backup, &addr, &size) < 0) 11364 + continue; 11365 + } 11405 11366 11406 11367 if (flag_delim) { 11407 11368 char *flag; ··· 11500 11455 tr->ref++; 11501 11456 } 11502 11457 11503 - if (start) { 11458 + /* 11459 + * Backup buffers can be freed but need vfree(). 11460 + */ 11461 + if (backup) 11462 + tr->flags |= TRACE_ARRAY_FL_VMALLOC; 11463 + 11464 + if (start || backup) { 11504 11465 tr->flags |= TRACE_ARRAY_FL_BOOT | TRACE_ARRAY_FL_LAST_BOOT; 11505 11466 tr->range_name = no_free_ptr(rname); 11506 11467 }
+1
kernel/trace/trace.h
··· 454 454 TRACE_ARRAY_FL_LAST_BOOT = BIT(2), 455 455 TRACE_ARRAY_FL_MOD_INIT = BIT(3), 456 456 TRACE_ARRAY_FL_MEMMAP = BIT(4), 457 + TRACE_ARRAY_FL_VMALLOC = BIT(5), 457 458 }; 458 459 459 460 #ifdef CONFIG_MODULES