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: Better separate SNAPSHOT and MAX_TRACE options

The latency tracers (scheduler, irqsoff, etc) were created when tracing
was first added. These tracers required a "snapshot" buffer that was the
same size as the ring buffer being written to. When a new max latency was
hit, the main ring buffer would swap with the snapshot buffer so that the
trace leading up to the latency would be saved in the snapshot buffer (The
snapshot buffer is never written to directly and the data within it can be
viewed without fear of being overwritten).

Later, a new feature was added to allow snapshots to be taken by user
space or even event triggers. This created a "snapshot" file that allowed
users to trigger a snapshot from user space to save the current trace.

The config for this new feature (CONFIG_TRACER_SNAPSHOT) would select the
latency tracer config (CONFIG_TRACER_MAX_LATENCY) as it would need all the
functionality from it as it already existed. But this was incorrect. As
the snapshot feature is really what the latency tracers need and not the
other way around.

Have CONFIG_TRACER_MAX_TRACE select CONFIG_TRACER_SNAPSHOT where the
tracers that needs the max latency buffer selects the TRACE_MAX_TRACE
which will then select TRACER_SNAPSHOT.

Also, go through trace.c and trace.h and make the code that only needs the
TRACER_MAX_TRACE protected by that and the code that always requires the
snapshot to be protected by TRACER_SNAPSHOT.

Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Link: https://patch.msgid.link/20260208183856.767870992@kernel.org
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>

+53 -47
+4 -4
kernel/trace/Kconfig
··· 133 133 134 134 config TRACER_MAX_TRACE 135 135 bool 136 + select TRACER_SNAPSHOT 136 137 137 138 config TRACE_CLOCK 138 139 bool ··· 423 422 select GENERIC_TRACER 424 423 select TRACER_MAX_TRACE 425 424 select RING_BUFFER_ALLOW_SWAP 426 - select TRACER_SNAPSHOT 427 425 select TRACER_SNAPSHOT_PER_CPU_SWAP 428 426 help 429 427 This option measures the time spent in irqs-off critical ··· 445 445 select GENERIC_TRACER 446 446 select TRACER_MAX_TRACE 447 447 select RING_BUFFER_ALLOW_SWAP 448 - select TRACER_SNAPSHOT 449 448 select TRACER_SNAPSHOT_PER_CPU_SWAP 450 449 select TRACE_PREEMPT_TOGGLE 451 450 help ··· 466 467 select GENERIC_TRACER 467 468 select CONTEXT_SWITCH_TRACER 468 469 select TRACER_MAX_TRACE 469 - select TRACER_SNAPSHOT 470 470 help 471 471 This tracer tracks the latency of the highest priority task 472 472 to be scheduled in, starting from the point it has woken up. ··· 615 617 616 618 config TRACER_SNAPSHOT 617 619 bool "Create a snapshot trace buffer" 618 - select TRACER_MAX_TRACE 619 620 help 620 621 Allow tracing users to take snapshot of the current buffer using the 621 622 ftrace interface, e.g.: 622 623 623 624 echo 1 > /sys/kernel/tracing/snapshot 624 625 cat snapshot 626 + 627 + Note, the latency tracers select this option. To disable it, 628 + all the latency tracers need to be disabled. 625 629 626 630 config TRACER_SNAPSHOT_PER_CPU_SWAP 627 631 bool "Allow snapshot to swap per CPU"
+38 -35
kernel/trace/trace.c
··· 825 825 return; 826 826 } 827 827 828 - /* Note, snapshot can not be used when the tracer uses it */ 829 - if (tracer_uses_snapshot(tr->current_trace)) { 830 - trace_array_puts(tr, "*** LATENCY TRACER ACTIVE ***\n"); 828 + if (tr->mapped) { 829 + trace_array_puts(tr, "*** BUFFER MEMORY MAPPED ***\n"); 831 830 trace_array_puts(tr, "*** Can not use snapshot (sorry) ***\n"); 832 831 return; 833 832 } 834 833 835 - if (tr->mapped) { 836 - trace_array_puts(tr, "*** BUFFER MEMORY MAPPED ***\n"); 834 + /* Note, snapshot can not be used when the tracer uses it */ 835 + if (tracer_uses_snapshot(tr->current_trace)) { 836 + trace_array_puts(tr, "*** LATENCY TRACER ACTIVE ***\n"); 837 837 trace_array_puts(tr, "*** Can not use snapshot (sorry) ***\n"); 838 838 return; 839 839 } ··· 1555 1555 __update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu) 1556 1556 { 1557 1557 struct array_buffer *trace_buf = &tr->array_buffer; 1558 - struct array_buffer *max_buf = &tr->snapshot_buffer; 1559 1558 struct trace_array_cpu *data = per_cpu_ptr(trace_buf->data, cpu); 1559 + struct array_buffer *max_buf = &tr->snapshot_buffer; 1560 1560 struct trace_array_cpu *max_data = per_cpu_ptr(max_buf->data, cpu); 1561 1561 1562 1562 max_buf->cpu = cpu; ··· 1585 1585 tracing_record_cmdline(tsk); 1586 1586 latency_fsnotify(tr); 1587 1587 } 1588 + #else 1589 + static inline void trace_create_maxlat_file(struct trace_array *tr, 1590 + struct dentry *d_tracer) { } 1591 + static inline void __update_max_tr(struct trace_array *tr, 1592 + struct task_struct *tsk, int cpu) { } 1593 + #endif /* CONFIG_TRACER_MAX_TRACE */ 1588 1594 1595 + #ifdef CONFIG_TRACER_SNAPSHOT 1589 1596 /** 1590 1597 * update_max_tr - snapshot all trace buffers from global_trace to max_tr 1591 1598 * @tr: tracer ··· 1626 1619 else 1627 1620 ring_buffer_record_off(tr->snapshot_buffer.buffer); 1628 1621 1629 - #ifdef CONFIG_TRACER_SNAPSHOT 1630 1622 if (tr->cond_snapshot && !tr->cond_snapshot->update(tr, cond_data)) { 1631 1623 arch_spin_unlock(&tr->max_lock); 1632 1624 return; 1633 1625 } 1634 - #endif 1626 + 1635 1627 swap(tr->array_buffer.buffer, tr->snapshot_buffer.buffer); 1636 1628 1637 1629 __update_max_tr(tr, tsk, cpu); ··· 1685 1679 __update_max_tr(tr, tsk, cpu); 1686 1680 arch_spin_unlock(&tr->max_lock); 1687 1681 } 1688 - #else /* !CONFIG_TRACER_MAX_TRACE */ 1689 - static inline void trace_create_maxlat_file(struct trace_array *tr, 1690 - struct dentry *d_tracer) { } 1691 - #endif /* CONFIG_TRACER_MAX_TRACE */ 1682 + #endif /* CONFIG_TRACER_SNAPSHOT */ 1692 1683 1693 1684 struct pipe_wait { 1694 1685 struct trace_iterator *iter; ··· 1718 1715 ret = ring_buffer_wait(iter->array_buffer->buffer, iter->cpu_file, full, 1719 1716 wait_pipe_cond, &pwait); 1720 1717 1721 - #ifdef CONFIG_TRACER_MAX_TRACE 1718 + #ifdef CONFIG_TRACER_SNAPSHOT 1722 1719 /* 1723 1720 * Make sure this is still the snapshot buffer, as if a snapshot were 1724 1721 * to happen, this would now be the main buffer. ··· 2061 2058 continue; 2062 2059 tr->clear_trace = false; 2063 2060 tracing_reset_online_cpus(&tr->array_buffer); 2064 - #ifdef CONFIG_TRACER_MAX_TRACE 2061 + #ifdef CONFIG_TRACER_SNAPSHOT 2065 2062 tracing_reset_online_cpus(&tr->snapshot_buffer); 2066 2063 #endif 2067 2064 } ··· 2101 2098 if (buffer) 2102 2099 ring_buffer_record_enable(buffer); 2103 2100 2104 - #ifdef CONFIG_TRACER_MAX_TRACE 2101 + #ifdef CONFIG_TRACER_SNAPSHOT 2105 2102 buffer = tr->snapshot_buffer.buffer; 2106 2103 if (buffer) 2107 2104 ring_buffer_record_enable(buffer); ··· 2137 2134 if (buffer) 2138 2135 ring_buffer_record_disable(buffer); 2139 2136 2140 - #ifdef CONFIG_TRACER_MAX_TRACE 2137 + #ifdef CONFIG_TRACER_SNAPSHOT 2141 2138 buffer = tr->snapshot_buffer.buffer; 2142 2139 if (buffer) 2143 2140 ring_buffer_record_disable(buffer); ··· 3760 3757 "# MAY BE MISSING FUNCTION EVENTS\n"); 3761 3758 } 3762 3759 3763 - #ifdef CONFIG_TRACER_MAX_TRACE 3760 + #ifdef CONFIG_TRACER_SNAPSHOT 3764 3761 static void show_snapshot_main_help(struct seq_file *m) 3765 3762 { 3766 3763 seq_puts(m, "# echo 0 > snapshot : Clears and frees snapshot buffer\n" ··· 3938 3935 3939 3936 iter->tr = tr; 3940 3937 3941 - #ifdef CONFIG_TRACER_MAX_TRACE 3938 + #ifdef CONFIG_TRACER_SNAPSHOT 3942 3939 /* Currently only the top directory has a snapshot */ 3943 3940 if (tr->current_trace->print_max || snapshot) 3944 3941 iter->array_buffer = &tr->snapshot_buffer; ··· 4354 4351 if (cpumask_test_cpu(cpu, tr->tracing_cpumask) && 4355 4352 !cpumask_test_cpu(cpu, tracing_cpumask_new)) { 4356 4353 ring_buffer_record_disable_cpu(tr->array_buffer.buffer, cpu); 4357 - #ifdef CONFIG_TRACER_MAX_TRACE 4354 + #ifdef CONFIG_TRACER_SNAPSHOT 4358 4355 ring_buffer_record_disable_cpu(tr->snapshot_buffer.buffer, cpu); 4359 4356 #endif 4360 4357 } 4361 4358 if (!cpumask_test_cpu(cpu, tr->tracing_cpumask) && 4362 4359 cpumask_test_cpu(cpu, tracing_cpumask_new)) { 4363 4360 ring_buffer_record_enable_cpu(tr->array_buffer.buffer, cpu); 4364 - #ifdef CONFIG_TRACER_MAX_TRACE 4361 + #ifdef CONFIG_TRACER_SNAPSHOT 4365 4362 ring_buffer_record_enable_cpu(tr->snapshot_buffer.buffer, cpu); 4366 4363 #endif 4367 4364 } ··· 4571 4568 4572 4569 case TRACE_ITER(OVERWRITE): 4573 4570 ring_buffer_change_overwrite(tr->array_buffer.buffer, enabled); 4574 - #ifdef CONFIG_TRACER_MAX_TRACE 4571 + #ifdef CONFIG_TRACER_SNAPSHOT 4575 4572 ring_buffer_change_overwrite(tr->snapshot_buffer.buffer, enabled); 4576 4573 #endif 4577 4574 break; ··· 5235 5232 } 5236 5233 } 5237 5234 5238 - #ifdef CONFIG_TRACER_MAX_TRACE 5235 + #ifdef CONFIG_TRACER_SNAPSHOT 5239 5236 /* resize @tr's buffer to the size of @size_tr's entries */ 5240 5237 static int resize_buffer_duplicate_size(struct array_buffer *trace_buf, 5241 5238 struct array_buffer *size_buf, int cpu_id) ··· 5261 5258 5262 5259 return ret; 5263 5260 } 5264 - #endif /* CONFIG_TRACER_MAX_TRACE */ 5261 + #endif /* CONFIG_TRACER_SNAPSHOT */ 5265 5262 5266 5263 static int __tracing_resize_ring_buffer(struct trace_array *tr, 5267 5264 unsigned long size, int cpu) ··· 5286 5283 if (ret < 0) 5287 5284 goto out_start; 5288 5285 5289 - #ifdef CONFIG_TRACER_MAX_TRACE 5286 + #ifdef CONFIG_TRACER_SNAPSHOT 5290 5287 if (!tr->allocated_snapshot) 5291 5288 goto out; 5292 5289 ··· 5318 5315 update_buffer_entries(&tr->snapshot_buffer, cpu); 5319 5316 5320 5317 out: 5321 - #endif /* CONFIG_TRACER_MAX_TRACE */ 5318 + #endif /* CONFIG_TRACER_SNAPSHOT */ 5322 5319 5323 5320 update_buffer_entries(&tr->array_buffer, cpu); 5324 5321 out_start: ··· 7023 7020 */ 7024 7021 tracing_reset_online_cpus(&tr->array_buffer); 7025 7022 7026 - #ifdef CONFIG_TRACER_MAX_TRACE 7023 + #ifdef CONFIG_TRACER_SNAPSHOT 7027 7024 if (tr->snapshot_buffer.buffer) 7028 7025 ring_buffer_set_clock(tr->snapshot_buffer.buffer, trace_clocks[i].func); 7029 7026 tracing_reset_online_cpus(&tr->snapshot_buffer); ··· 8170 8167 return 0; 8171 8168 } 8172 8169 8173 - #ifdef CONFIG_TRACER_MAX_TRACE 8170 + #ifdef CONFIG_TRACER_SNAPSHOT 8174 8171 static int get_snapshot_map(struct trace_array *tr) 8175 8172 { 8176 8173 int err = 0; ··· 9174 9171 if (ret) 9175 9172 goto out; 9176 9173 9177 - #ifdef CONFIG_TRACER_MAX_TRACE 9174 + #ifdef CONFIG_TRACER_SNAPSHOT 9178 9175 9179 9176 if (!tr->allocated_snapshot) 9180 9177 goto out_max; ··· 9395 9392 if (ret) 9396 9393 return ret; 9397 9394 9398 - #ifdef CONFIG_TRACER_MAX_TRACE 9395 + #ifdef CONFIG_TRACER_SNAPSHOT 9399 9396 /* Fix mapped buffer trace arrays do not have snapshot buffers */ 9400 9397 if (tr->range_addr_start) 9401 9398 return 0; ··· 9422 9419 free_trace_buffer(&tr->array_buffer); 9423 9420 kfree(tr->module_delta); 9424 9421 9425 - #ifdef CONFIG_TRACER_MAX_TRACE 9422 + #ifdef CONFIG_TRACER_SNAPSHOT 9426 9423 free_trace_buffer(&tr->snapshot_buffer); 9427 9424 #endif 9428 9425 } ··· 9564 9561 tr->syscall_buf_sz = global_trace.syscall_buf_sz; 9565 9562 9566 9563 tr->max_lock = (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED; 9567 - #ifdef CONFIG_TRACER_MAX_TRACE 9564 + #ifdef CONFIG_TRACER_SNAPSHOT 9568 9565 spin_lock_init(&tr->snapshot_trigger_lock); 9569 9566 #endif 9570 9567 tr->current_trace = &nop_trace; ··· 10518 10515 return done; 10519 10516 } 10520 10517 10521 - #ifdef CONFIG_TRACER_MAX_TRACE 10518 + #ifdef CONFIG_TRACER_SNAPSHOT 10522 10519 __init static bool tr_needs_alloc_snapshot(const char *name) 10523 10520 { 10524 10521 char *test; ··· 10708 10705 } 10709 10706 } else { 10710 10707 /* Only non mapped buffers have snapshot buffers */ 10711 - if (IS_ENABLED(CONFIG_TRACER_MAX_TRACE)) 10708 + if (IS_ENABLED(CONFIG_TRACER_SNAPSHOT)) 10712 10709 do_allocate_snapshot(name); 10713 10710 } 10714 10711 ··· 10835 10832 global_trace.current_trace_flags = nop_trace.flags; 10836 10833 10837 10834 global_trace.max_lock = (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED; 10838 - #ifdef CONFIG_TRACER_MAX_TRACE 10835 + #ifdef CONFIG_TRACER_SNAPSHOT 10839 10836 spin_lock_init(&global_trace.snapshot_trigger_lock); 10840 10837 #endif 10841 10838 ftrace_init_global_array_ops(&global_trace); ··· 10903 10900 10904 10901 void __init ftrace_boot_snapshot(void) 10905 10902 { 10906 - #ifdef CONFIG_TRACER_MAX_TRACE 10903 + #ifdef CONFIG_TRACER_SNAPSHOT 10907 10904 struct trace_array *tr; 10908 10905 10909 10906 if (!snapshot_at_boot)
+11 -8
kernel/trace/trace.h
··· 329 329 struct list_head list; 330 330 char *name; 331 331 struct array_buffer array_buffer; 332 - #ifdef CONFIG_TRACER_MAX_TRACE 332 + #ifdef CONFIG_TRACER_SNAPSHOT 333 333 /* 334 334 * The snapshot_buffer is used to snapshot the trace when a maximum 335 335 * latency is reached, or when the user initiates a snapshot. ··· 346 346 bool allocated_snapshot; 347 347 spinlock_t snapshot_trigger_lock; 348 348 unsigned int snapshot; 349 + #ifdef CONFIG_TRACER_MAX_TRACE 349 350 unsigned long max_latency; 350 351 #ifdef CONFIG_FSNOTIFY 351 352 struct dentry *d_max_latency; 352 353 struct work_struct fsnotify_work; 353 354 struct irq_work fsnotify_irqwork; 354 - #endif 355 - #endif 355 + #endif /* CONFIG_FSNOTIFY */ 356 + #endif /* CONFIG_TRACER_MAX_TRACE */ 357 + #endif /* CONFIG_TRACER_SNAPSHOT */ 358 + 356 359 /* The below is for memory mapped ring buffer */ 357 360 unsigned int mapped; 358 361 unsigned long range_addr_start; ··· 381 378 * 382 379 * It is also used in other places outside the update_max_tr 383 380 * so it needs to be defined outside of the 384 - * CONFIG_TRACER_MAX_TRACE. 381 + * CONFIG_TRACER_SNAPSHOT. 385 382 */ 386 383 arch_spinlock_t max_lock; 387 384 #ifdef CONFIG_FTRACE_SYSCALLS ··· 794 791 struct trace_pid_list **new_pid_list, 795 792 const char __user *ubuf, size_t cnt); 796 793 797 - #ifdef CONFIG_TRACER_MAX_TRACE 794 + #ifdef CONFIG_TRACER_SNAPSHOT 798 795 void update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu, 799 796 void *cond_data); 800 797 void update_max_tr_single(struct trace_array *tr, 801 798 struct task_struct *tsk, int cpu); 802 799 803 - #ifdef CONFIG_FSNOTIFY 804 - #define LATENCY_FS_NOTIFY 800 + #if defined(CONFIG_TRACER_MAX_TRACE) && defined(CONFIG_FSNOTIFY) 801 + # define LATENCY_FS_NOTIFY 805 802 #endif 806 - #endif /* CONFIG_TRACER_MAX_TRACE */ 807 803 808 804 #ifdef LATENCY_FS_NOTIFY 809 805 void latency_fsnotify(struct trace_array *tr); 810 806 #else 811 807 static inline void latency_fsnotify(struct trace_array *tr) { } 812 808 #endif 809 + #endif /* CONFIG_TRACER_SNAPSHOT */ 813 810 814 811 #ifdef CONFIG_STACKTRACE 815 812 void __trace_stack(struct trace_array *tr, unsigned int trace_ctx, int skip);