From nobody Sun Feb 8 11:26:44 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3A3352F5A2A for ; Sat, 15 Nov 2025 14:09:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763215757; cv=none; b=ti7Rm31SaGl+Y+lc5jFb1ioc1YMLq2nlz+BnXva5o9CVXbkQ1wOY0YeOUeoqq2FgFUNdNlT635V8DpS0Tsry/zf3TXCVIVcLwAc/LMUTPyuAXF6hB6xiMa3fKqP+4WJ1jeaQuLvwP5YP84VZ8AK3bDZrLnCV7RMiNcAgwFixX0M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763215757; c=relaxed/simple; bh=/jqkeyUMX0k98d1YiY61xd3cyAETJz3GjeyWP6J++Fs=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=jQ5dvD+eV7EIlp2Fh62IHlMoEYgMzVPdJCJ7Kqejo8maati7W7MsD1pbacojV7D5ndY4iUBE/I1rKTUgHQ+RipZrXesuTdiRs/c8youjBa1T0IED9bV83YD7VRRyX5ukoFnDUZOrFkP6q1fOTRcj4qyy8fYIiAk757FcJPXjCZ0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=IcKiTqWG; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="IcKiTqWG" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C2FAEC113D0; Sat, 15 Nov 2025 14:09:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1763215756; bh=/jqkeyUMX0k98d1YiY61xd3cyAETJz3GjeyWP6J++Fs=; h=Date:From:To:Cc:Subject:References:From; b=IcKiTqWG9W5vJh1VmbnsDmQ3A+DmweTX8ChJ9G/I0vCkVzfq7AeZJn4NS+f8TAaS2 Xl11PNbc60KPgrA2XNEc/15oFBynpw7jHwNpYeiStfd7butwS1Jc6JXWJba25Ocxe1 zGrgMPQrNSK9FYKLIgoUGz7lqYy5b9PKKpeTY9hceVnR9dSPMWYXBXMGt9RR+7Np1K TUlrhCx+y10LqXeN6oUSBfYD6KGO3QT6e8WJAkDygAJGaJBbZzelfb6pdUfeJSJj0G 9eH9LnuyeVGLIQpAUcE/rQYFSTTms0xNRUA277aU5D4DwoAo2lw+S2s3jyVNwhwO3S W37rnLMl+U3XA== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1vKGy9-00000002AuI-0WPg; Sat, 15 Nov 2025 09:09:37 -0500 Message-ID: <20251115140936.984627654@kernel.org> User-Agent: quilt/0.68 Date: Sat, 15 Nov 2025 09:09:14 -0500 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton Subject: [for-next][PATCH 4/5] tracing: Have function graph tracer option sleep-time be per instance References: <20251115140910.386662473@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Steven Rostedt 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 Cc: Mark Rutland Cc: Mathieu Desnoyers Cc: Andrew Morton Link: https://patch.msgid.link/20251114192318.950255167@kernel.org Fixes: c132be2c4fcc1 ("function_graph: Have the instances use their own ftr= ace_ops for filtering") Signed-off-by: Steven Rostedt (Google) --- kernel/trace/fgraph.c | 10 +---- kernel/trace/ftrace.c | 4 +- kernel/trace/trace.h | 5 +-- kernel/trace/trace_functions_graph.c | 64 +++++++++++++++++++++++----- 4 files changed, 60 insertions(+), 23 deletions(-) diff --git a/kernel/trace/fgraph.c b/kernel/trace/fgraph.c index 484ad7a18463..7fb9b169d6d4 100644 --- a/kernel/trace/fgraph.c +++ b/kernel/trace/fgraph.c @@ -498,9 +498,6 @@ void *fgraph_retrieve_parent_data(int idx, int *size_by= tes, int depth) return get_data_type_data(current, offset); } =20 -/* Both enabled by default (can be cleared by function_graph tracer flags = */ -bool fgraph_sleep_time =3D true; - #ifdef CONFIG_DYNAMIC_FTRACE /* * archs can override this function if they must do something @@ -1023,11 +1020,6 @@ void fgraph_init_ops(struct ftrace_ops *dst_ops, #endif } =20 -void ftrace_graph_sleep_time_control(bool enable) -{ - fgraph_sleep_time =3D enable; -} - /* * Simply points to ftrace_stub, but with the proper protocol. * Defined by the linker script in linux/vmlinux.lds.h @@ -1098,7 +1090,7 @@ ftrace_graph_probe_sched_switch(void *ignore, bool pr= eempt, * Does the user want to count the time a function was asleep. * If so, do not update the time stamps. */ - if (fgraph_sleep_time) + if (!fgraph_no_sleep_time) return; =20 timestamp =3D trace_clock_local(); diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index ab601cd9638b..7c3bbebeec7a 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -862,6 +862,8 @@ static int profile_graph_entry(struct ftrace_graph_ent = *trace, return 1; } =20 +bool fprofile_no_sleep_time; + static void profile_graph_return(struct ftrace_graph_ret *trace, struct fgraph_ops *gops, struct ftrace_regs *fregs) @@ -887,7 +889,7 @@ static void profile_graph_return(struct ftrace_graph_re= t *trace, =20 calltime =3D rettime - profile_data->calltime; =20 - if (!fgraph_sleep_time) { + if (fprofile_no_sleep_time) { if (current->ftrace_sleeptime) calltime -=3D current->ftrace_sleeptime - profile_data->sleeptime; } diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 41b416a22450..58be6d741d72 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -943,8 +943,6 @@ static __always_inline bool ftrace_hash_empty(struct ft= race_hash *hash) #define TRACE_GRAPH_PRINT_FILL_SHIFT 28 #define TRACE_GRAPH_PRINT_FILL_MASK (0x3 << TRACE_GRAPH_PRINT_FILL_SHIFT) =20 -extern void ftrace_graph_sleep_time_control(bool enable); - #ifdef CONFIG_FUNCTION_PROFILER extern void ftrace_graph_graph_time_control(bool enable); #else @@ -1115,7 +1113,8 @@ static inline void ftrace_graph_addr_finish(struct fg= raph_ops *gops, struct ftra #endif /* CONFIG_DYNAMIC_FTRACE */ =20 extern unsigned int fgraph_max_depth; -extern bool fgraph_sleep_time; +extern unsigned int fgraph_no_sleep_time; +extern bool fprofile_no_sleep_time; =20 static inline bool ftrace_graph_ignore_func(struct fgraph_ops *gops, struct ftrace_graph_ent = *trace) diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_func= tions_graph.c index 53adbe4bfedb..12315eb65925 100644 --- a/kernel/trace/trace_functions_graph.c +++ b/kernel/trace/trace_functions_graph.c @@ -19,6 +19,9 @@ /* When set, irq functions might be ignored */ static int ftrace_graph_skip_irqs; =20 +/* Do not record function time when task is sleeping */ +unsigned int fgraph_no_sleep_time; + struct fgraph_cpu_data { pid_t last_pid; int depth; @@ -239,13 +242,14 @@ static int graph_entry(struct ftrace_graph_ent *trace, if (ftrace_graph_ignore_irqs(tr)) return 0; =20 - if (fgraph_sleep_time) { - /* Only need to record the calltime */ - ftimes =3D fgraph_reserve_data(gops->idx, sizeof(ftimes->calltime)); - } else { + if (fgraph_no_sleep_time && + !tracer_flags_is_set(tr, TRACE_GRAPH_SLEEP_TIME)) { ftimes =3D fgraph_reserve_data(gops->idx, sizeof(*ftimes)); if (ftimes) ftimes->sleeptime =3D current->ftrace_sleeptime; + } else { + /* Only need to record the calltime */ + ftimes =3D fgraph_reserve_data(gops->idx, sizeof(ftimes->calltime)); } if (!ftimes) return 0; @@ -331,11 +335,15 @@ void __trace_graph_return(struct trace_array *tr, trace_buffer_unlock_commit_nostack(buffer, event); } =20 -static void handle_nosleeptime(struct ftrace_graph_ret *trace, +static void handle_nosleeptime(struct trace_array *tr, + struct ftrace_graph_ret *trace, struct fgraph_times *ftimes, int size) { - if (fgraph_sleep_time || size < sizeof(*ftimes)) + if (size < sizeof(*ftimes)) + return; + + if (!fgraph_no_sleep_time || tracer_flags_is_set(tr, TRACE_GRAPH_SLEEP_TI= ME)) return; =20 ftimes->calltime +=3D current->ftrace_sleeptime - ftimes->sleeptime; @@ -364,7 +372,7 @@ void trace_graph_return(struct ftrace_graph_ret *trace, if (!ftimes) return; =20 - handle_nosleeptime(trace, ftimes, size); + handle_nosleeptime(tr, trace, ftimes, size); =20 calltime =3D ftimes->calltime; =20 @@ -377,6 +385,7 @@ static void trace_graph_thresh_return(struct ftrace_gra= ph_ret *trace, struct ftrace_regs *fregs) { struct fgraph_times *ftimes; + struct trace_array *tr; int size; =20 ftrace_graph_addr_finish(gops, trace); @@ -390,7 +399,8 @@ static void trace_graph_thresh_return(struct ftrace_gra= ph_ret *trace, if (!ftimes) return; =20 - handle_nosleeptime(trace, ftimes, size); + tr =3D gops->private; + handle_nosleeptime(tr, trace, ftimes, size); =20 if (tracing_thresh && (trace_clock_local() - ftimes->calltime < tracing_thresh)) @@ -452,6 +462,9 @@ static int graph_trace_init(struct trace_array *tr) if (!tracer_flags_is_set(tr, TRACE_GRAPH_PRINT_IRQS)) ftrace_graph_skip_irqs++; =20 + if (!tracer_flags_is_set(tr, TRACE_GRAPH_SLEEP_TIME)) + fgraph_no_sleep_time++; + /* Make gops functions visible before we start tracing */ smp_mb(); =20 @@ -494,6 +507,11 @@ static void graph_trace_reset(struct trace_array *tr) if (WARN_ON_ONCE(ftrace_graph_skip_irqs < 0)) ftrace_graph_skip_irqs =3D 0; =20 + if (!tracer_flags_is_set(tr, TRACE_GRAPH_SLEEP_TIME)) + fgraph_no_sleep_time--; + if (WARN_ON_ONCE(fgraph_no_sleep_time < 0)) + fgraph_no_sleep_time =3D 0; + tracing_stop_cmdline_record(); unregister_ftrace_graph(tr->gops); } @@ -1619,8 +1637,24 @@ void graph_trace_close(struct trace_iterator *iter) static int func_graph_set_flag(struct trace_array *tr, u32 old_flags, u32 bit, int se= t) { - if (bit =3D=3D TRACE_GRAPH_SLEEP_TIME) - ftrace_graph_sleep_time_control(set); +/* + * The function profiler gets updated even if function graph + * isn't the current tracer. Handle it separately. + */ +#ifdef CONFIG_FUNCTION_PROFILER + if (bit =3D=3D TRACE_GRAPH_SLEEP_TIME && (tr->flags & TRACE_ARRAY_FL_GLOB= AL) && + !!set =3D=3D fprofile_no_sleep_time) { + if (set) { + fgraph_no_sleep_time--; + if (WARN_ON_ONCE(fgraph_no_sleep_time < 0)) + fgraph_no_sleep_time =3D 0; + fprofile_no_sleep_time =3D false; + } else { + fgraph_no_sleep_time++; + fprofile_no_sleep_time =3D true; + } + } +#endif =20 /* Do nothing if the current tracer is not this tracer */ if (tr->current_trace !=3D &graph_trace) @@ -1630,6 +1664,16 @@ func_graph_set_flag(struct trace_array *tr, u32 old_= flags, u32 bit, int set) if (!!set =3D=3D !!(tr->current_trace_flags->val & bit)) return 0; =20 + if (bit =3D=3D TRACE_GRAPH_SLEEP_TIME) { + if (set) { + fgraph_no_sleep_time--; + if (WARN_ON_ONCE(fgraph_no_sleep_time < 0)) + fgraph_no_sleep_time =3D 0; + } else { + fgraph_no_sleep_time++; + } + } + if (bit =3D=3D TRACE_GRAPH_PRINT_IRQS) { if (set) ftrace_graph_skip_irqs--; --=20 2.51.0