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: 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: c132be2c4fcc1 ("function_graph: Have the instances use their own ftrace_ops for filtering")
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>

+60 -23
+1 -9
kernel/trace/fgraph.c
··· 498 498 return get_data_type_data(current, offset); 499 499 } 500 500 501 - /* Both enabled by default (can be cleared by function_graph tracer flags */ 502 - bool fgraph_sleep_time = true; 503 - 504 501 #ifdef CONFIG_DYNAMIC_FTRACE 505 502 /* 506 503 * archs can override this function if they must do something ··· 1020 1023 #endif 1021 1024 } 1022 1025 1023 - void ftrace_graph_sleep_time_control(bool enable) 1024 - { 1025 - fgraph_sleep_time = enable; 1026 - } 1027 - 1028 1026 /* 1029 1027 * Simply points to ftrace_stub, but with the proper protocol. 1030 1028 * Defined by the linker script in linux/vmlinux.lds.h ··· 1090 1098 * Does the user want to count the time a function was asleep. 1091 1099 * If so, do not update the time stamps. 1092 1100 */ 1093 - if (fgraph_sleep_time) 1101 + if (!fgraph_no_sleep_time) 1094 1102 return; 1095 1103 1096 1104 timestamp = trace_clock_local();
+3 -1
kernel/trace/ftrace.c
··· 862 862 return 1; 863 863 } 864 864 865 + bool fprofile_no_sleep_time; 866 + 865 867 static void profile_graph_return(struct ftrace_graph_ret *trace, 866 868 struct fgraph_ops *gops, 867 869 struct ftrace_regs *fregs) ··· 889 887 890 888 calltime = rettime - profile_data->calltime; 891 889 892 - if (!fgraph_sleep_time) { 890 + if (fprofile_no_sleep_time) { 893 891 if (current->ftrace_sleeptime) 894 892 calltime -= current->ftrace_sleeptime - profile_data->sleeptime; 895 893 }
+2 -3
kernel/trace/trace.h
··· 943 943 #define TRACE_GRAPH_PRINT_FILL_SHIFT 28 944 944 #define TRACE_GRAPH_PRINT_FILL_MASK (0x3 << TRACE_GRAPH_PRINT_FILL_SHIFT) 945 945 946 - extern void ftrace_graph_sleep_time_control(bool enable); 947 - 948 946 #ifdef CONFIG_FUNCTION_PROFILER 949 947 extern void ftrace_graph_graph_time_control(bool enable); 950 948 #else ··· 1113 1115 #endif /* CONFIG_DYNAMIC_FTRACE */ 1114 1116 1115 1117 extern unsigned int fgraph_max_depth; 1116 - extern bool fgraph_sleep_time; 1118 + extern unsigned int fgraph_no_sleep_time; 1119 + extern bool fprofile_no_sleep_time; 1117 1120 1118 1121 static inline bool 1119 1122 ftrace_graph_ignore_func(struct fgraph_ops *gops, struct ftrace_graph_ent *trace)
+54 -10
kernel/trace/trace_functions_graph.c
··· 19 19 /* When set, irq functions might be ignored */ 20 20 static int ftrace_graph_skip_irqs; 21 21 22 + /* Do not record function time when task is sleeping */ 23 + unsigned int fgraph_no_sleep_time; 24 + 22 25 struct fgraph_cpu_data { 23 26 pid_t last_pid; 24 27 int depth; ··· 242 239 if (ftrace_graph_ignore_irqs(tr)) 243 240 return 0; 244 241 245 - if (fgraph_sleep_time) { 246 - /* Only need to record the calltime */ 247 - ftimes = fgraph_reserve_data(gops->idx, sizeof(ftimes->calltime)); 248 - } else { 242 + if (fgraph_no_sleep_time && 243 + !tracer_flags_is_set(tr, TRACE_GRAPH_SLEEP_TIME)) { 249 244 ftimes = fgraph_reserve_data(gops->idx, sizeof(*ftimes)); 250 245 if (ftimes) 251 246 ftimes->sleeptime = current->ftrace_sleeptime; 247 + } else { 248 + /* Only need to record the calltime */ 249 + ftimes = fgraph_reserve_data(gops->idx, sizeof(ftimes->calltime)); 252 250 } 253 251 if (!ftimes) 254 252 return 0; ··· 335 331 trace_buffer_unlock_commit_nostack(buffer, event); 336 332 } 337 333 338 - static void handle_nosleeptime(struct ftrace_graph_ret *trace, 334 + static void handle_nosleeptime(struct trace_array *tr, 335 + struct ftrace_graph_ret *trace, 339 336 struct fgraph_times *ftimes, 340 337 int size) 341 338 { 342 - if (fgraph_sleep_time || size < sizeof(*ftimes)) 339 + if (size < sizeof(*ftimes)) 340 + return; 341 + 342 + if (!fgraph_no_sleep_time || tracer_flags_is_set(tr, TRACE_GRAPH_SLEEP_TIME)) 343 343 return; 344 344 345 345 ftimes->calltime += current->ftrace_sleeptime - ftimes->sleeptime; ··· 372 364 if (!ftimes) 373 365 return; 374 366 375 - handle_nosleeptime(trace, ftimes, size); 367 + handle_nosleeptime(tr, trace, ftimes, size); 376 368 377 369 calltime = ftimes->calltime; 378 370 ··· 385 377 struct ftrace_regs *fregs) 386 378 { 387 379 struct fgraph_times *ftimes; 380 + struct trace_array *tr; 388 381 int size; 389 382 390 383 ftrace_graph_addr_finish(gops, trace); ··· 399 390 if (!ftimes) 400 391 return; 401 392 402 - handle_nosleeptime(trace, ftimes, size); 393 + tr = gops->private; 394 + handle_nosleeptime(tr, trace, ftimes, size); 403 395 404 396 if (tracing_thresh && 405 397 (trace_clock_local() - ftimes->calltime < tracing_thresh)) ··· 462 452 if (!tracer_flags_is_set(tr, TRACE_GRAPH_PRINT_IRQS)) 463 453 ftrace_graph_skip_irqs++; 464 454 455 + if (!tracer_flags_is_set(tr, TRACE_GRAPH_SLEEP_TIME)) 456 + fgraph_no_sleep_time++; 457 + 465 458 /* Make gops functions visible before we start tracing */ 466 459 smp_mb(); 467 460 ··· 506 493 ftrace_graph_skip_irqs--; 507 494 if (WARN_ON_ONCE(ftrace_graph_skip_irqs < 0)) 508 495 ftrace_graph_skip_irqs = 0; 496 + 497 + if (!tracer_flags_is_set(tr, TRACE_GRAPH_SLEEP_TIME)) 498 + fgraph_no_sleep_time--; 499 + if (WARN_ON_ONCE(fgraph_no_sleep_time < 0)) 500 + fgraph_no_sleep_time = 0; 509 501 510 502 tracing_stop_cmdline_record(); 511 503 unregister_ftrace_graph(tr->gops); ··· 1637 1619 static int 1638 1620 func_graph_set_flag(struct trace_array *tr, u32 old_flags, u32 bit, int set) 1639 1621 { 1640 - if (bit == TRACE_GRAPH_SLEEP_TIME) 1641 - ftrace_graph_sleep_time_control(set); 1622 + /* 1623 + * The function profiler gets updated even if function graph 1624 + * isn't the current tracer. Handle it separately. 1625 + */ 1626 + #ifdef CONFIG_FUNCTION_PROFILER 1627 + if (bit == TRACE_GRAPH_SLEEP_TIME && (tr->flags & TRACE_ARRAY_FL_GLOBAL) && 1628 + !!set == fprofile_no_sleep_time) { 1629 + if (set) { 1630 + fgraph_no_sleep_time--; 1631 + if (WARN_ON_ONCE(fgraph_no_sleep_time < 0)) 1632 + fgraph_no_sleep_time = 0; 1633 + fprofile_no_sleep_time = false; 1634 + } else { 1635 + fgraph_no_sleep_time++; 1636 + fprofile_no_sleep_time = true; 1637 + } 1638 + } 1639 + #endif 1642 1640 1643 1641 /* Do nothing if the current tracer is not this tracer */ 1644 1642 if (tr->current_trace != &graph_trace) ··· 1663 1629 /* Do nothing if already set. */ 1664 1630 if (!!set == !!(tr->current_trace_flags->val & bit)) 1665 1631 return 0; 1632 + 1633 + if (bit == TRACE_GRAPH_SLEEP_TIME) { 1634 + if (set) { 1635 + fgraph_no_sleep_time--; 1636 + if (WARN_ON_ONCE(fgraph_no_sleep_time < 0)) 1637 + fgraph_no_sleep_time = 0; 1638 + } else { 1639 + fgraph_no_sleep_time++; 1640 + } 1641 + } 1666 1642 1667 1643 if (bit == TRACE_GRAPH_PRINT_IRQS) { 1668 1644 if (set)