Skip to content

Commit c4f1fe4

Browse files
committed
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>
1 parent e4c1a09 commit c4f1fe4

3 files changed

Lines changed: 53 additions & 47 deletions

File tree

kernel/trace/Kconfig

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ config BUILDTIME_MCOUNT_SORT
133133

134134
config TRACER_MAX_TRACE
135135
bool
136+
select TRACER_SNAPSHOT
136137

137138
config TRACE_CLOCK
138139
bool
@@ -422,7 +423,6 @@ config IRQSOFF_TRACER
422423
select GENERIC_TRACER
423424
select TRACER_MAX_TRACE
424425
select RING_BUFFER_ALLOW_SWAP
425-
select TRACER_SNAPSHOT
426426
select TRACER_SNAPSHOT_PER_CPU_SWAP
427427
help
428428
This option measures the time spent in irqs-off critical
@@ -445,7 +445,6 @@ config PREEMPT_TRACER
445445
select GENERIC_TRACER
446446
select TRACER_MAX_TRACE
447447
select RING_BUFFER_ALLOW_SWAP
448-
select TRACER_SNAPSHOT
449448
select TRACER_SNAPSHOT_PER_CPU_SWAP
450449
select TRACE_PREEMPT_TOGGLE
451450
help
@@ -467,7 +466,6 @@ config SCHED_TRACER
467466
select GENERIC_TRACER
468467
select CONTEXT_SWITCH_TRACER
469468
select TRACER_MAX_TRACE
470-
select TRACER_SNAPSHOT
471469
help
472470
This tracer tracks the latency of the highest priority task
473471
to be scheduled in, starting from the point it has woken up.
@@ -617,14 +615,16 @@ config TRACE_SYSCALL_BUF_SIZE_DEFAULT
617615

618616
config TRACER_SNAPSHOT
619617
bool "Create a snapshot trace buffer"
620-
select TRACER_MAX_TRACE
621618
help
622619
Allow tracing users to take snapshot of the current buffer using the
623620
ftrace interface, e.g.:
624621

625622
echo 1 > /sys/kernel/tracing/snapshot
626623
cat snapshot
627624

625+
Note, the latency tracers select this option. To disable it,
626+
all the latency tracers need to be disabled.
627+
628628
config TRACER_SNAPSHOT_PER_CPU_SWAP
629629
bool "Allow snapshot to swap per CPU"
630630
depends on TRACER_SNAPSHOT

kernel/trace/trace.c

Lines changed: 38 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -825,15 +825,15 @@ static void tracing_snapshot_instance_cond(struct trace_array *tr,
825825
return;
826826
}
827827

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");
831830
trace_array_puts(tr, "*** Can not use snapshot (sorry) ***\n");
832831
return;
833832
}
834833

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");
837837
trace_array_puts(tr, "*** Can not use snapshot (sorry) ***\n");
838838
return;
839839
}
@@ -1555,8 +1555,8 @@ static void
15551555
__update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)
15561556
{
15571557
struct array_buffer *trace_buf = &tr->array_buffer;
1558-
struct array_buffer *max_buf = &tr->snapshot_buffer;
15591558
struct trace_array_cpu *data = per_cpu_ptr(trace_buf->data, cpu);
1559+
struct array_buffer *max_buf = &tr->snapshot_buffer;
15601560
struct trace_array_cpu *max_data = per_cpu_ptr(max_buf->data, cpu);
15611561

15621562
max_buf->cpu = cpu;
@@ -1585,7 +1585,14 @@ __update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)
15851585
tracing_record_cmdline(tsk);
15861586
latency_fsnotify(tr);
15871587
}
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 */
15881594

1595+
#ifdef CONFIG_TRACER_SNAPSHOT
15891596
/**
15901597
* update_max_tr - snapshot all trace buffers from global_trace to max_tr
15911598
* @tr: tracer
@@ -1619,12 +1626,11 @@ update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu,
16191626
else
16201627
ring_buffer_record_off(tr->snapshot_buffer.buffer);
16211628

1622-
#ifdef CONFIG_TRACER_SNAPSHOT
16231629
if (tr->cond_snapshot && !tr->cond_snapshot->update(tr, cond_data)) {
16241630
arch_spin_unlock(&tr->max_lock);
16251631
return;
16261632
}
1627-
#endif
1633+
16281634
swap(tr->array_buffer.buffer, tr->snapshot_buffer.buffer);
16291635

16301636
__update_max_tr(tr, tsk, cpu);
@@ -1679,10 +1685,7 @@ update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu)
16791685
__update_max_tr(tr, tsk, cpu);
16801686
arch_spin_unlock(&tr->max_lock);
16811687
}
1682-
#else /* !CONFIG_TRACER_MAX_TRACE */
1683-
static inline void trace_create_maxlat_file(struct trace_array *tr,
1684-
struct dentry *d_tracer) { }
1685-
#endif /* CONFIG_TRACER_MAX_TRACE */
1688+
#endif /* CONFIG_TRACER_SNAPSHOT */
16861689

16871690
struct pipe_wait {
16881691
struct trace_iterator *iter;
@@ -1715,7 +1718,7 @@ static int wait_on_pipe(struct trace_iterator *iter, int full)
17151718
ret = ring_buffer_wait(iter->array_buffer->buffer, iter->cpu_file, full,
17161719
wait_pipe_cond, &pwait);
17171720

1718-
#ifdef CONFIG_TRACER_MAX_TRACE
1721+
#ifdef CONFIG_TRACER_SNAPSHOT
17191722
/*
17201723
* Make sure this is still the snapshot buffer, as if a snapshot were
17211724
* to happen, this would now be the main buffer.
@@ -2058,7 +2061,7 @@ void tracing_reset_all_online_cpus_unlocked(void)
20582061
continue;
20592062
tr->clear_trace = false;
20602063
tracing_reset_online_cpus(&tr->array_buffer);
2061-
#ifdef CONFIG_TRACER_MAX_TRACE
2064+
#ifdef CONFIG_TRACER_SNAPSHOT
20622065
tracing_reset_online_cpus(&tr->snapshot_buffer);
20632066
#endif
20642067
}
@@ -2098,7 +2101,7 @@ static void tracing_start_tr(struct trace_array *tr)
20982101
if (buffer)
20992102
ring_buffer_record_enable(buffer);
21002103

2101-
#ifdef CONFIG_TRACER_MAX_TRACE
2104+
#ifdef CONFIG_TRACER_SNAPSHOT
21022105
buffer = tr->snapshot_buffer.buffer;
21032106
if (buffer)
21042107
ring_buffer_record_enable(buffer);
@@ -2134,7 +2137,7 @@ static void tracing_stop_tr(struct trace_array *tr)
21342137
if (buffer)
21352138
ring_buffer_record_disable(buffer);
21362139

2137-
#ifdef CONFIG_TRACER_MAX_TRACE
2140+
#ifdef CONFIG_TRACER_SNAPSHOT
21382141
buffer = tr->snapshot_buffer.buffer;
21392142
if (buffer)
21402143
ring_buffer_record_disable(buffer);
@@ -3757,7 +3760,7 @@ static void test_ftrace_alive(struct seq_file *m)
37573760
"# MAY BE MISSING FUNCTION EVENTS\n");
37583761
}
37593762

3760-
#ifdef CONFIG_TRACER_MAX_TRACE
3763+
#ifdef CONFIG_TRACER_SNAPSHOT
37613764
static void show_snapshot_main_help(struct seq_file *m)
37623765
{
37633766
seq_puts(m, "# echo 0 > snapshot : Clears and frees snapshot buffer\n"
@@ -3935,7 +3938,7 @@ __tracing_open(struct inode *inode, struct file *file, bool snapshot)
39353938

39363939
iter->tr = tr;
39373940

3938-
#ifdef CONFIG_TRACER_MAX_TRACE
3941+
#ifdef CONFIG_TRACER_SNAPSHOT
39393942
/* Currently only the top directory has a snapshot */
39403943
if (tr->current_trace->print_max || snapshot)
39413944
iter->array_buffer = &tr->snapshot_buffer;
@@ -4351,14 +4354,14 @@ int tracing_set_cpumask(struct trace_array *tr,
43514354
if (cpumask_test_cpu(cpu, tr->tracing_cpumask) &&
43524355
!cpumask_test_cpu(cpu, tracing_cpumask_new)) {
43534356
ring_buffer_record_disable_cpu(tr->array_buffer.buffer, cpu);
4354-
#ifdef CONFIG_TRACER_MAX_TRACE
4357+
#ifdef CONFIG_TRACER_SNAPSHOT
43554358
ring_buffer_record_disable_cpu(tr->snapshot_buffer.buffer, cpu);
43564359
#endif
43574360
}
43584361
if (!cpumask_test_cpu(cpu, tr->tracing_cpumask) &&
43594362
cpumask_test_cpu(cpu, tracing_cpumask_new)) {
43604363
ring_buffer_record_enable_cpu(tr->array_buffer.buffer, cpu);
4361-
#ifdef CONFIG_TRACER_MAX_TRACE
4364+
#ifdef CONFIG_TRACER_SNAPSHOT
43624365
ring_buffer_record_enable_cpu(tr->snapshot_buffer.buffer, cpu);
43634366
#endif
43644367
}
@@ -4568,7 +4571,7 @@ int set_tracer_flag(struct trace_array *tr, u64 mask, int enabled)
45684571

45694572
case TRACE_ITER(OVERWRITE):
45704573
ring_buffer_change_overwrite(tr->array_buffer.buffer, enabled);
4571-
#ifdef CONFIG_TRACER_MAX_TRACE
4574+
#ifdef CONFIG_TRACER_SNAPSHOT
45724575
ring_buffer_change_overwrite(tr->snapshot_buffer.buffer, enabled);
45734576
#endif
45744577
break;
@@ -5232,7 +5235,7 @@ static void update_buffer_entries(struct array_buffer *buf, int cpu)
52325235
}
52335236
}
52345237

5235-
#ifdef CONFIG_TRACER_MAX_TRACE
5238+
#ifdef CONFIG_TRACER_SNAPSHOT
52365239
/* resize @tr's buffer to the size of @size_tr's entries */
52375240
static int resize_buffer_duplicate_size(struct array_buffer *trace_buf,
52385241
struct array_buffer *size_buf, int cpu_id)
@@ -5258,7 +5261,7 @@ static int resize_buffer_duplicate_size(struct array_buffer *trace_buf,
52585261

52595262
return ret;
52605263
}
5261-
#endif /* CONFIG_TRACER_MAX_TRACE */
5264+
#endif /* CONFIG_TRACER_SNAPSHOT */
52625265

52635266
static int __tracing_resize_ring_buffer(struct trace_array *tr,
52645267
unsigned long size, int cpu)
@@ -5283,7 +5286,7 @@ static int __tracing_resize_ring_buffer(struct trace_array *tr,
52835286
if (ret < 0)
52845287
goto out_start;
52855288

5286-
#ifdef CONFIG_TRACER_MAX_TRACE
5289+
#ifdef CONFIG_TRACER_SNAPSHOT
52875290
if (!tr->allocated_snapshot)
52885291
goto out;
52895292

@@ -5315,7 +5318,7 @@ static int __tracing_resize_ring_buffer(struct trace_array *tr,
53155318
update_buffer_entries(&tr->snapshot_buffer, cpu);
53165319

53175320
out:
5318-
#endif /* CONFIG_TRACER_MAX_TRACE */
5321+
#endif /* CONFIG_TRACER_SNAPSHOT */
53195322

53205323
update_buffer_entries(&tr->array_buffer, cpu);
53215324
out_start:
@@ -7020,7 +7023,7 @@ int tracing_set_clock(struct trace_array *tr, const char *clockstr)
70207023
*/
70217024
tracing_reset_online_cpus(&tr->array_buffer);
70227025

7023-
#ifdef CONFIG_TRACER_MAX_TRACE
7026+
#ifdef CONFIG_TRACER_SNAPSHOT
70247027
if (tr->snapshot_buffer.buffer)
70257028
ring_buffer_set_clock(tr->snapshot_buffer.buffer, trace_clocks[i].func);
70267029
tracing_reset_online_cpus(&tr->snapshot_buffer);
@@ -8167,7 +8170,7 @@ static long tracing_buffers_ioctl(struct file *file, unsigned int cmd, unsigned
81678170
return 0;
81688171
}
81698172

8170-
#ifdef CONFIG_TRACER_MAX_TRACE
8173+
#ifdef CONFIG_TRACER_SNAPSHOT
81718174
static int get_snapshot_map(struct trace_array *tr)
81728175
{
81738176
int err = 0;
@@ -9171,7 +9174,7 @@ buffer_subbuf_size_write(struct file *filp, const char __user *ubuf,
91719174
if (ret)
91729175
goto out;
91739176

9174-
#ifdef CONFIG_TRACER_MAX_TRACE
9177+
#ifdef CONFIG_TRACER_SNAPSHOT
91759178

91769179
if (!tr->allocated_snapshot)
91779180
goto out_max;
@@ -9392,7 +9395,7 @@ static int allocate_trace_buffers(struct trace_array *tr, int size)
93929395
if (ret)
93939396
return ret;
93949397

9395-
#ifdef CONFIG_TRACER_MAX_TRACE
9398+
#ifdef CONFIG_TRACER_SNAPSHOT
93969399
/* Fix mapped buffer trace arrays do not have snapshot buffers */
93979400
if (tr->range_addr_start)
93989401
return 0;
@@ -9419,7 +9422,7 @@ static void free_trace_buffers(struct trace_array *tr)
94199422
free_trace_buffer(&tr->array_buffer);
94209423
kfree(tr->module_delta);
94219424

9422-
#ifdef CONFIG_TRACER_MAX_TRACE
9425+
#ifdef CONFIG_TRACER_SNAPSHOT
94239426
free_trace_buffer(&tr->snapshot_buffer);
94249427
#endif
94259428
}
@@ -9561,7 +9564,7 @@ trace_array_create_systems(const char *name, const char *systems,
95619564
tr->syscall_buf_sz = global_trace.syscall_buf_sz;
95629565

95639566
tr->max_lock = (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED;
9564-
#ifdef CONFIG_TRACER_MAX_TRACE
9567+
#ifdef CONFIG_TRACER_SNAPSHOT
95659568
spin_lock_init(&tr->snapshot_trigger_lock);
95669569
#endif
95679570
tr->current_trace = &nop_trace;
@@ -10515,7 +10518,7 @@ ssize_t trace_parse_run_command(struct file *file, const char __user *buffer,
1051510518
return done;
1051610519
}
1051710520

10518-
#ifdef CONFIG_TRACER_MAX_TRACE
10521+
#ifdef CONFIG_TRACER_SNAPSHOT
1051910522
__init static bool tr_needs_alloc_snapshot(const char *name)
1052010523
{
1052110524
char *test;
@@ -10705,7 +10708,7 @@ __init static void enable_instances(void)
1070510708
}
1070610709
} else {
1070710710
/* Only non mapped buffers have snapshot buffers */
10708-
if (IS_ENABLED(CONFIG_TRACER_MAX_TRACE))
10711+
if (IS_ENABLED(CONFIG_TRACER_SNAPSHOT))
1070910712
do_allocate_snapshot(name);
1071010713
}
1071110714

@@ -10832,7 +10835,7 @@ __init static int tracer_alloc_buffers(void)
1083210835
global_trace.current_trace_flags = nop_trace.flags;
1083310836

1083410837
global_trace.max_lock = (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED;
10835-
#ifdef CONFIG_TRACER_MAX_TRACE
10838+
#ifdef CONFIG_TRACER_SNAPSHOT
1083610839
spin_lock_init(&global_trace.snapshot_trigger_lock);
1083710840
#endif
1083810841
ftrace_init_global_array_ops(&global_trace);
@@ -10900,7 +10903,7 @@ struct trace_array *trace_get_global_array(void)
1090010903

1090110904
void __init ftrace_boot_snapshot(void)
1090210905
{
10903-
#ifdef CONFIG_TRACER_MAX_TRACE
10906+
#ifdef CONFIG_TRACER_SNAPSHOT
1090410907
struct trace_array *tr;
1090510908

1090610909
if (!snapshot_at_boot)

kernel/trace/trace.h

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ struct trace_array {
329329
struct list_head list;
330330
char *name;
331331
struct array_buffer array_buffer;
332-
#ifdef CONFIG_TRACER_MAX_TRACE
332+
#ifdef CONFIG_TRACER_SNAPSHOT
333333
/*
334334
* The snapshot_buffer is used to snapshot the trace when a maximum
335335
* latency is reached, or when the user initiates a snapshot.
@@ -346,13 +346,16 @@ struct trace_array {
346346
bool allocated_snapshot;
347347
spinlock_t snapshot_trigger_lock;
348348
unsigned int snapshot;
349+
#ifdef CONFIG_TRACER_MAX_TRACE
349350
unsigned long max_latency;
350351
#ifdef CONFIG_FSNOTIFY
351352
struct dentry *d_max_latency;
352353
struct work_struct fsnotify_work;
353354
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+
356359
/* The below is for memory mapped ring buffer */
357360
unsigned int mapped;
358361
unsigned long range_addr_start;
@@ -378,7 +381,7 @@ struct trace_array {
378381
*
379382
* It is also used in other places outside the update_max_tr
380383
* so it needs to be defined outside of the
381-
* CONFIG_TRACER_MAX_TRACE.
384+
* CONFIG_TRACER_SNAPSHOT.
382385
*/
383386
arch_spinlock_t max_lock;
384387
#ifdef CONFIG_FTRACE_SYSCALLS
@@ -791,22 +794,22 @@ int trace_pid_write(struct trace_pid_list *filtered_pids,
791794
struct trace_pid_list **new_pid_list,
792795
const char __user *ubuf, size_t cnt);
793796

794-
#ifdef CONFIG_TRACER_MAX_TRACE
797+
#ifdef CONFIG_TRACER_SNAPSHOT
795798
void update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu,
796799
void *cond_data);
797800
void update_max_tr_single(struct trace_array *tr,
798801
struct task_struct *tsk, int cpu);
799802

800-
#ifdef CONFIG_FSNOTIFY
801-
#define LATENCY_FS_NOTIFY
803+
#if defined(CONFIG_TRACER_MAX_TRACE) && defined(CONFIG_FSNOTIFY)
804+
# define LATENCY_FS_NOTIFY
802805
#endif
803-
#endif /* CONFIG_TRACER_MAX_TRACE */
804806

805807
#ifdef LATENCY_FS_NOTIFY
806808
void latency_fsnotify(struct trace_array *tr);
807809
#else
808810
static inline void latency_fsnotify(struct trace_array *tr) { }
809811
#endif
812+
#endif /* CONFIG_TRACER_SNAPSHOT */
810813

811814
#ifdef CONFIG_STACKTRACE
812815
void __trace_stack(struct trace_array *tr, unsigned int trace_ctx, int skip);

0 commit comments

Comments
 (0)