On Sat, 28 Mar 2026 14:18:42 -0600 Wesley Atwell <[email protected]> wrote:
> Some tracing boot parameters already accept delimited value lists, but > their __setup() handlers keep only the last instance seen at boot. > Make repeated instances append to the same boot-time buffer in the > format each parser already consumes. > > Use a shared trace_append_boot_param() helper for the ftrace filters, > trace_options, and kprobe_event boot parameters. trace_trigger= > tokenizes its backing storage in place, so keep a running offset and > only parse the newly appended chunk into bootup_triggers[]. > > This also lets Bootconfig array values work naturally when they expand > to repeated param=value entries. > > Validated by booting with repeated ftrace_filter=, ftrace_notrace=, > ftrace_graph_filter=, ftrace_graph_notrace=, trace_options=, > kprobe_event=, and trace_trigger= parameters and confirming that the > resulting tracefs state preserved every requested entry. Before this > change, only the last instance from each repeated parameter survived > boot. > > Signed-off-by: Wesley Atwell <[email protected]> > --- > v5: FYI, it's nice to have a daisy chain connection of previous versions. I suggest instead of just saying "v5:" use: Changes since v4: https://lore.kernel.org/all/[email protected]/ > - use int sizes in the shared append helper and trace_trigger bookkeeping > - keep a single bounded append path that only inserts the separator after > the first entry > - only advance the trace_trigger buffer offset after a successful append > > kernel/trace/ftrace.c | 12 ++++++++---- > kernel/trace/trace.c | 29 ++++++++++++++++++++++++++++- > kernel/trace/trace.h | 2 ++ > kernel/trace/trace_events.c | 23 ++++++++++++++++++++--- > kernel/trace/trace_kprobe.c | 3 ++- > 5 files changed, 60 insertions(+), 9 deletions(-) > > +/* > + * Repeated boot parameters, including Bootconfig array expansions, need > + * to stay in the delimiter form that the existing parser consumes. > + */ > +void __init trace_append_boot_param(char *buf, const char *str, char sep, > + int size) > +{ This is much better. > + int len, needed, str_len; > + > + if (!*str) > + return; > + > + len = strlen(buf); > + str_len = strlen(str); > + needed = len + str_len + 1; Perhaps add a comment: /* For continuation, account for separator */ > + if (len) > + needed++; > + if (needed > size) > + return; > + > + if (len) > + buf[len++] = sep; > + > + strscpy(buf + len, str, size - len); > +} > + > static int __init set_cmdline_ftrace(char *str) > { > strscpy(bootup_tracer_buf, str, MAX_TRACER_SIZE); > --- a/kernel/trace/trace_events.c > +++ b/kernel/trace/trace_events.c > @@ -3679,20 +3679,37 @@ static struct boot_triggers { > } bootup_triggers[MAX_BOOT_TRIGGERS]; > > static char bootup_trigger_buf[COMMAND_LINE_SIZE]; > +static int bootup_trigger_buf_len; > static int nr_boot_triggers; > > static __init int setup_trace_triggers(char *str) > { > + char *slot; > char *trigger; > char *buf; > int i; > > - strscpy(bootup_trigger_buf, str, COMMAND_LINE_SIZE); > + if (bootup_trigger_buf_len >= COMMAND_LINE_SIZE) > + return 1; > + > + slot = bootup_trigger_buf + bootup_trigger_buf_len; The bootup_trigger_buf is a temporary buffer for this function only. It works fine as is. There's no reason to modify this function. -- Steve > + > + /* > + * trace_trigger= parsing tokenizes the backing storage in place. > + * Copy each repeated parameter into fresh space and only parse that > + * newly copied chunk here. > + */ > + trace_append_boot_param(slot, str, '\0', > + COMMAND_LINE_SIZE - bootup_trigger_buf_len); > + if (!*slot) > + return 1; > + > + bootup_trigger_buf_len += strlen(slot) + 1; > trace_set_ring_buffer_expanded(NULL); > disable_tracing_selftest("running event triggers"); > > - buf = bootup_trigger_buf; > - for (i = 0; i < MAX_BOOT_TRIGGERS; i++) { > + buf = slot; > + for (i = nr_boot_triggers; i < MAX_BOOT_TRIGGERS; i++) { > trigger = strsep(&buf, ","); > if (!trigger) > break;
