Skip to content

Commit 5abb6cc

Browse files
committed
tracing: Have function graph tracer option sleep-time be per instance
Currently the option to have function graph tracer to ignore time spent when a task is sleeping is global when the interface is per-instance. Changing the value in one instance will affect the results of another instance that is also running the function graph tracer. This can lead to confusing results. 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/20251114192318.950255167@kernel.org Fixes: c132be2 ("function_graph: Have the instances use their own ftrace_ops for filtering") Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
1 parent 4132886 commit 5abb6cc

4 files changed

Lines changed: 60 additions & 23 deletions

File tree

kernel/trace/fgraph.c

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -498,9 +498,6 @@ void *fgraph_retrieve_parent_data(int idx, int *size_bytes, int depth)
498498
return get_data_type_data(current, offset);
499499
}
500500

501-
/* Both enabled by default (can be cleared by function_graph tracer flags */
502-
bool fgraph_sleep_time = true;
503-
504501
#ifdef CONFIG_DYNAMIC_FTRACE
505502
/*
506503
* archs can override this function if they must do something
@@ -1023,11 +1020,6 @@ void fgraph_init_ops(struct ftrace_ops *dst_ops,
10231020
#endif
10241021
}
10251022

1026-
void ftrace_graph_sleep_time_control(bool enable)
1027-
{
1028-
fgraph_sleep_time = enable;
1029-
}
1030-
10311023
/*
10321024
* Simply points to ftrace_stub, but with the proper protocol.
10331025
* Defined by the linker script in linux/vmlinux.lds.h
@@ -1098,7 +1090,7 @@ ftrace_graph_probe_sched_switch(void *ignore, bool preempt,
10981090
* Does the user want to count the time a function was asleep.
10991091
* If so, do not update the time stamps.
11001092
*/
1101-
if (fgraph_sleep_time)
1093+
if (!fgraph_no_sleep_time)
11021094
return;
11031095

11041096
timestamp = trace_clock_local();

kernel/trace/ftrace.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -862,6 +862,8 @@ static int profile_graph_entry(struct ftrace_graph_ent *trace,
862862
return 1;
863863
}
864864

865+
bool fprofile_no_sleep_time;
866+
865867
static void profile_graph_return(struct ftrace_graph_ret *trace,
866868
struct fgraph_ops *gops,
867869
struct ftrace_regs *fregs)
@@ -887,7 +889,7 @@ static void profile_graph_return(struct ftrace_graph_ret *trace,
887889

888890
calltime = rettime - profile_data->calltime;
889891

890-
if (!fgraph_sleep_time) {
892+
if (fprofile_no_sleep_time) {
891893
if (current->ftrace_sleeptime)
892894
calltime -= current->ftrace_sleeptime - profile_data->sleeptime;
893895
}

kernel/trace/trace.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -943,8 +943,6 @@ static __always_inline bool ftrace_hash_empty(struct ftrace_hash *hash)
943943
#define TRACE_GRAPH_PRINT_FILL_SHIFT 28
944944
#define TRACE_GRAPH_PRINT_FILL_MASK (0x3 << TRACE_GRAPH_PRINT_FILL_SHIFT)
945945

946-
extern void ftrace_graph_sleep_time_control(bool enable);
947-
948946
#ifdef CONFIG_FUNCTION_PROFILER
949947
extern void ftrace_graph_graph_time_control(bool enable);
950948
#else
@@ -1115,7 +1113,8 @@ static inline void ftrace_graph_addr_finish(struct fgraph_ops *gops, struct ftra
11151113
#endif /* CONFIG_DYNAMIC_FTRACE */
11161114

11171115
extern unsigned int fgraph_max_depth;
1118-
extern bool fgraph_sleep_time;
1116+
extern unsigned int fgraph_no_sleep_time;
1117+
extern bool fprofile_no_sleep_time;
11191118

11201119
static inline bool
11211120
ftrace_graph_ignore_func(struct fgraph_ops *gops, struct ftrace_graph_ent *trace)

kernel/trace/trace_functions_graph.c

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
/* When set, irq functions might be ignored */
2020
static int ftrace_graph_skip_irqs;
2121

22+
/* Do not record function time when task is sleeping */
23+
unsigned int fgraph_no_sleep_time;
24+
2225
struct fgraph_cpu_data {
2326
pid_t last_pid;
2427
int depth;
@@ -239,13 +242,14 @@ static int graph_entry(struct ftrace_graph_ent *trace,
239242
if (ftrace_graph_ignore_irqs(tr))
240243
return 0;
241244

242-
if (fgraph_sleep_time) {
243-
/* Only need to record the calltime */
244-
ftimes = fgraph_reserve_data(gops->idx, sizeof(ftimes->calltime));
245-
} else {
245+
if (fgraph_no_sleep_time &&
246+
!tracer_flags_is_set(tr, TRACE_GRAPH_SLEEP_TIME)) {
246247
ftimes = fgraph_reserve_data(gops->idx, sizeof(*ftimes));
247248
if (ftimes)
248249
ftimes->sleeptime = current->ftrace_sleeptime;
250+
} else {
251+
/* Only need to record the calltime */
252+
ftimes = fgraph_reserve_data(gops->idx, sizeof(ftimes->calltime));
249253
}
250254
if (!ftimes)
251255
return 0;
@@ -331,11 +335,15 @@ void __trace_graph_return(struct trace_array *tr,
331335
trace_buffer_unlock_commit_nostack(buffer, event);
332336
}
333337

334-
static void handle_nosleeptime(struct ftrace_graph_ret *trace,
338+
static void handle_nosleeptime(struct trace_array *tr,
339+
struct ftrace_graph_ret *trace,
335340
struct fgraph_times *ftimes,
336341
int size)
337342
{
338-
if (fgraph_sleep_time || size < sizeof(*ftimes))
343+
if (size < sizeof(*ftimes))
344+
return;
345+
346+
if (!fgraph_no_sleep_time || tracer_flags_is_set(tr, TRACE_GRAPH_SLEEP_TIME))
339347
return;
340348

341349
ftimes->calltime += current->ftrace_sleeptime - ftimes->sleeptime;
@@ -364,7 +372,7 @@ void trace_graph_return(struct ftrace_graph_ret *trace,
364372
if (!ftimes)
365373
return;
366374

367-
handle_nosleeptime(trace, ftimes, size);
375+
handle_nosleeptime(tr, trace, ftimes, size);
368376

369377
calltime = ftimes->calltime;
370378

@@ -377,6 +385,7 @@ static void trace_graph_thresh_return(struct ftrace_graph_ret *trace,
377385
struct ftrace_regs *fregs)
378386
{
379387
struct fgraph_times *ftimes;
388+
struct trace_array *tr;
380389
int size;
381390

382391
ftrace_graph_addr_finish(gops, trace);
@@ -390,7 +399,8 @@ static void trace_graph_thresh_return(struct ftrace_graph_ret *trace,
390399
if (!ftimes)
391400
return;
392401

393-
handle_nosleeptime(trace, ftimes, size);
402+
tr = gops->private;
403+
handle_nosleeptime(tr, trace, ftimes, size);
394404

395405
if (tracing_thresh &&
396406
(trace_clock_local() - ftimes->calltime < tracing_thresh))
@@ -452,6 +462,9 @@ static int graph_trace_init(struct trace_array *tr)
452462
if (!tracer_flags_is_set(tr, TRACE_GRAPH_PRINT_IRQS))
453463
ftrace_graph_skip_irqs++;
454464

465+
if (!tracer_flags_is_set(tr, TRACE_GRAPH_SLEEP_TIME))
466+
fgraph_no_sleep_time++;
467+
455468
/* Make gops functions visible before we start tracing */
456469
smp_mb();
457470

@@ -494,6 +507,11 @@ static void graph_trace_reset(struct trace_array *tr)
494507
if (WARN_ON_ONCE(ftrace_graph_skip_irqs < 0))
495508
ftrace_graph_skip_irqs = 0;
496509

510+
if (!tracer_flags_is_set(tr, TRACE_GRAPH_SLEEP_TIME))
511+
fgraph_no_sleep_time--;
512+
if (WARN_ON_ONCE(fgraph_no_sleep_time < 0))
513+
fgraph_no_sleep_time = 0;
514+
497515
tracing_stop_cmdline_record();
498516
unregister_ftrace_graph(tr->gops);
499517
}
@@ -1619,8 +1637,24 @@ void graph_trace_close(struct trace_iterator *iter)
16191637
static int
16201638
func_graph_set_flag(struct trace_array *tr, u32 old_flags, u32 bit, int set)
16211639
{
1622-
if (bit == TRACE_GRAPH_SLEEP_TIME)
1623-
ftrace_graph_sleep_time_control(set);
1640+
/*
1641+
* The function profiler gets updated even if function graph
1642+
* isn't the current tracer. Handle it separately.
1643+
*/
1644+
#ifdef CONFIG_FUNCTION_PROFILER
1645+
if (bit == TRACE_GRAPH_SLEEP_TIME && (tr->flags & TRACE_ARRAY_FL_GLOBAL) &&
1646+
!!set == fprofile_no_sleep_time) {
1647+
if (set) {
1648+
fgraph_no_sleep_time--;
1649+
if (WARN_ON_ONCE(fgraph_no_sleep_time < 0))
1650+
fgraph_no_sleep_time = 0;
1651+
fprofile_no_sleep_time = false;
1652+
} else {
1653+
fgraph_no_sleep_time++;
1654+
fprofile_no_sleep_time = true;
1655+
}
1656+
}
1657+
#endif
16241658

16251659
/* Do nothing if the current tracer is not this tracer */
16261660
if (tr->current_trace != &graph_trace)
@@ -1630,6 +1664,16 @@ func_graph_set_flag(struct trace_array *tr, u32 old_flags, u32 bit, int set)
16301664
if (!!set == !!(tr->current_trace_flags->val & bit))
16311665
return 0;
16321666

1667+
if (bit == TRACE_GRAPH_SLEEP_TIME) {
1668+
if (set) {
1669+
fgraph_no_sleep_time--;
1670+
if (WARN_ON_ONCE(fgraph_no_sleep_time < 0))
1671+
fgraph_no_sleep_time = 0;
1672+
} else {
1673+
fgraph_no_sleep_time++;
1674+
}
1675+
}
1676+
16331677
if (bit == TRACE_GRAPH_PRINT_IRQS) {
16341678
if (set)
16351679
ftrace_graph_skip_irqs--;

0 commit comments

Comments
 (0)