[PATCH v3] tracing: fgraph: fix the quadratic shadow stack walk

From: Vineet Gupta

Date: Thu Oct 01 2026 - 06:38:34 EST


alloc_retstack_tasklist() assigns a shadow stack to every thread when
fgraph is enabled. It did so FTRACE_RETSTACK_ALLOC_SIZE (32) tasks at a
time, and since for_each_process_thread() has no cursor, every sweep
restarted from init_task and re-walked the tasks already served, making
the ftrace_graph_active 0 -> 1 transition quadratic in the thread count.
On a 60-core Sapphire Rapids machine with 400000 idle threads it took
227 s, inside a single bpf() syscall for the kprobe_multi case.

Allocating inline with GFP_NOWAIT removes the batching: a single sweep
serves every task, 227 s -> 0.092 s.

v1: https://lore.kernel.org/all/20260922225526.1554758-1-vineet.gupta@xxxxxxxxx/
v2: https://lore.kernel.org/all/20260929005411.4105448-1-vineet.gupta@xxxxxxxxx/

Changes since v2:
- update the stale alloc_retstack_tasklist() comment, which still
described the old batch-of-32 behaviour (bot+bpf-ci)

Sashiko flagged the mix of goto-based cleanup and scoped_guard() in
this function. Peter and Andrii both considered it fine as is, so it
is unchanged:
https://lore.kernel.org/all/20260929080346.GR4120091@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/

Changes since v1:
- replace both v1 patches with Peter's inline GFP_NOWAIT approach,
which removes the quadratic behaviour rather than dividing it by a
constant. With a single sweep there is no retry loop left, so the
v1 cond_resched() patch has nothing to attach to and is dropped.
- comment why returning from inside scoped_guard() skips the free
loop safely

Vineet Gupta (1):
tracing: fgraph: allocate shadow stacks inline with GFP_NOWAIT

kernel/trace/fgraph.c | 44 ++++++++++++++++++++++++++++---------------
1 file changed, 29 insertions(+), 15 deletions(-)

--
2.53.0-Meta