Skip to content

Commit 0a663b7

Browse files
haryvenrostedt
authored andcommitted
tracing: Fix syscall events activation by ensuring refcount hits zero
When multiple syscall events are specified in the kernel command line (e.g., trace_event=syscalls:sys_enter_openat,syscalls:sys_enter_close), they are often not captured after boot, even though they appear enabled in the tracing/set_event file. The issue stems from how syscall events are initialized. Syscall tracepoints require the global reference count (sys_tracepoint_refcount) to transition from 0 to 1 to trigger the registration of the syscall work (TIF_SYSCALL_TRACEPOINT) for tasks, including the init process (pid 1). The current implementation of early_enable_events() with disable_first=true used an interleaved sequence of "Disable A -> Enable A -> Disable B -> Enable B". If multiple syscalls are enabled, the refcount never drops to zero, preventing the 0->1 transition that triggers actual registration. Fix this by splitting early_enable_events() into two distinct phases: 1. Disable all events specified in the buffer. 2. Enable all events specified in the buffer. This ensures the refcount hits zero before re-enabling, allowing syscall events to be properly activated during early boot. The code is also refactored to use a helper function to avoid logic duplication between the disable and enable phases. Cc: [email protected] Cc: Masami Hiramatsu <[email protected]> Cc: Mathieu Desnoyers <[email protected]> Link: https://patch.msgid.link/[email protected] Fixes: ce1039b ("tracing: Fix enabling of syscall events on the command line") Signed-off-by: Huiwen He <[email protected]> Signed-off-by: Steven Rostedt (Google) <[email protected]>
1 parent b96d0c5 commit 0a663b7

1 file changed

Lines changed: 37 additions & 15 deletions

File tree

kernel/trace/trace_events.c

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4668,26 +4668,22 @@ static __init int event_trace_memsetup(void)
46684668
return 0;
46694669
}
46704670

4671-
__init void
4672-
early_enable_events(struct trace_array *tr, char *buf, bool disable_first)
4671+
/*
4672+
* Helper function to enable or disable a comma-separated list of events
4673+
* from the bootup buffer.
4674+
*/
4675+
static __init void __early_set_events(struct trace_array *tr, char *buf, bool enable)
46734676
{
46744677
char *token;
4675-
int ret;
4676-
4677-
while (true) {
4678-
token = strsep(&buf, ",");
4679-
4680-
if (!token)
4681-
break;
46824678

4679+
while ((token = strsep(&buf, ","))) {
46834680
if (*token) {
4684-
/* Restarting syscalls requires that we stop them first */
4685-
if (disable_first)
4681+
if (enable) {
4682+
if (ftrace_set_clr_event(tr, token, 1))
4683+
pr_warn("Failed to enable trace event: %s\n", token);
4684+
} else {
46864685
ftrace_set_clr_event(tr, token, 0);
4687-
4688-
ret = ftrace_set_clr_event(tr, token, 1);
4689-
if (ret)
4690-
pr_warn("Failed to enable trace event: %s\n", token);
4686+
}
46914687
}
46924688

46934689
/* Put back the comma to allow this to be called again */
@@ -4696,6 +4692,32 @@ early_enable_events(struct trace_array *tr, char *buf, bool disable_first)
46964692
}
46974693
}
46984694

4695+
/**
4696+
* early_enable_events - enable events from the bootup buffer
4697+
* @tr: The trace array to enable the events in
4698+
* @buf: The buffer containing the comma separated list of events
4699+
* @disable_first: If true, disable all events in @buf before enabling them
4700+
*
4701+
* This function enables events from the bootup buffer. If @disable_first
4702+
* is true, it will first disable all events in the buffer before enabling
4703+
* them.
4704+
*
4705+
* For syscall events, which rely on a global refcount to register the
4706+
* SYSCALL_WORK_SYSCALL_TRACEPOINT flag (especially for pid 1), we must
4707+
* ensure the refcount hits zero before re-enabling them. A simple
4708+
* "disable then enable" per-event is not enough if multiple syscalls are
4709+
* used, as the refcount will stay above zero. Thus, we need a two-phase
4710+
* approach: disable all, then enable all.
4711+
*/
4712+
__init void
4713+
early_enable_events(struct trace_array *tr, char *buf, bool disable_first)
4714+
{
4715+
if (disable_first)
4716+
__early_set_events(tr, buf, false);
4717+
4718+
__early_set_events(tr, buf, true);
4719+
}
4720+
46994721
static __init int event_trace_enable(void)
47004722
{
47014723
struct trace_array *tr = top_trace_array();

0 commit comments

Comments
 (0)