From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from relay.hostedemail.com (smtprelay0016.hostedemail.com [216.40.44.16]) (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 81BC2367B7F for ; Tue, 9 Jun 2026 21:52:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=216.40.44.16 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781041953; cv=none; b=EnjWTqKtYMGNF03xSLtkzhu2RWkI0pGg7BvTF1vc9Lt3XglYPz7DqzinBYakMbgqvyslS5lu6j3951E8RtqrG1kvOaJJntHgOEuj/9GK1+Lt60IjwN4sAsFEKd2DUKFCpALLCgcejlfWwh75RV9oVCheuKV9gCsAOshAYpgGcg4= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781041953; c=relaxed/simple; bh=I7gM0/TsQJUq2d6YwQu13+5Pq/boGx8EiasFnc9XK2I=; h=Date:From:To:Cc:Subject:Message-ID:MIME-Version:Content-Type; b=VAbEwZRBSWaSSZ8EzqNjX5lZVRHDNsAp4HLBYrrr6001/1e8AcluH71lTcznO1Lf9oizXEYka3jruL00uEZ6PkqiGmgtyeh6oomBzTkXIl4fDlWFFIpnk+Dqtj5u3oIUYj4SMCa6iaMJIVNnPPakgcDYYzrYMMRyzMwn5tKod3E= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=goodmis.org; spf=pass smtp.mailfrom=goodmis.org; arc=none smtp.client-ip=216.40.44.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=goodmis.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=goodmis.org Received: from omf15.hostedemail.com (lb01a-stub [10.200.18.249]) by unirelay10.hostedemail.com (Postfix) with ESMTP id 61E55C2790; Tue, 9 Jun 2026 21:52:24 +0000 (UTC) Received: from [HIDDEN] (Authenticated sender: rostedt@goodmis.org) by omf15.hostedemail.com (Postfix) with ESMTPA id B66ED1D; Tue, 9 Jun 2026 21:52:22 +0000 (UTC) Date: Tue, 9 Jun 2026 17:52:21 -0400 From: Steven Rostedt To: Linus Torvalds Cc: LKML , Tomas Glozar , John Kacur Subject: [GIT PULL] RTLA: Fixes for v7.1 Message-ID: <20260609175221.2d3eba1b@fedora> X-Mailer: Claws Mail 4.4.0 (GTK 3.24.52; x86_64-redhat-linux-gnu) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit X-Rspamd-Server: rspamout02 X-Rspamd-Queue-Id: B66ED1D X-Stat-Signature: ebi8y6ftghemg4okqwe678qo1ebrwcwe X-Session-Marker: 726F737465647440676F6F646D69732E6F7267 X-Session-ID: U2FsdGVkX1+NULase0AlLV8qCL73lcwkZMIK8Q8nQKU= X-HE-Tag: 1781041942-5567 X-HE-Meta: U2FsdGVkX18XEfeh5LRilakZSnHLT8tvqfuYMJ3VCsTTnZgSsGpC35XYNDJFMycHQQEaN6shS9JQPK77fneAbbRcWfSGbAmL1+L6mlYmLspRuPhVsE/dBEXkp2UfIxuEpXmUw5JquwxhcLKOkBChbOkTg7nhw3JDuOjtnk7DCNPUb1JOCGPhHH/ohuadQnFHOTwHIZhlg2GOf54i2hoyRWAqkBLb/3tTBtIihI3wfFFkeJqIA/IArLSR8wsKb0RwgYSW3Hh8T/Ozh4DFyS6waZ/3J2H9WR0bQe7L8NO/9fGiiet2HQi9HxvRKTaNG10oh0XMEEdE1d09gqUCwpStAw1ol/aGMU0mq7BCIdtT+P1Ow2DTXPMXBA== Linus, RTLA fixes for v7.1 - Fix multi-character short option parsing Fix regression in parsing of multiple-character short options (e.g. -p100 /= -p 100/, -un /= -u -n/) caused by getopt_long() internal state corruption after a refactoring. Please pull the latest trace-tools-v7.1-rc7 tree, which can be found at: git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace.git trace-tools-v7.1-rc7 Tag SHA1: 2e8078d1e4222de54231ab0285f29802a432ccb6 Head SHA1: e9e41d3035032ed6053d8bad7b7077e1cb3a6540 Tomas Glozar (1): rtla: Fix parsing of multi-character short options ---- tools/tracing/rtla/src/common.c | 28 +++++----------------------- tools/tracing/rtla/src/common.h | 12 +++++++++++- tools/tracing/rtla/src/osnoise_hist.c | 7 ++++--- tools/tracing/rtla/src/osnoise_top.c | 7 ++++--- tools/tracing/rtla/src/timerlat_hist.c | 7 ++++--- tools/tracing/rtla/src/timerlat_top.c | 7 ++++--- 6 files changed, 32 insertions(+), 36 deletions(-) --------------------------- commit e9e41d3035032ed6053d8bad7b7077e1cb3a6540 Author: Tomas Glozar Date: Tue Jun 2 14:55:06 2026 +0200 rtla: Fix parsing of multi-character short options A bug was reported where the parsing of multi-character short options, be it a short option with an argument specified without space (e.g. "-p100") or multiple short options in one argument (e.g. -un), ignores options specific to individual tools. Furthermore, if the rest of the option is supposed to be an argument, it gets reinterpreted as a string of options. For example, -p100 gets interpreted as -100, which is due to hackish implementation read as --no-thread --no-irq --no-irq with timerlat hist, causing rtla to error out: $ rtla timerlat hist -p100 no-irq and no-thread set, there is nothing to do here This behavior is caused by getopt_long() being called twice on each argument, once in common_parse_options(), once in [tool]_parse_args(): - common_parse_options() calls getopt_long() with an array of options common for all rtla tools, while suppressing errors (opterr = 0). - If the option fails to parse, common_parse_options() returns 0. - If 0 is returned from common_parse_options(), [tool]_parse_args() calls getopt_long() again, with its own set of options. * [tool] means one of {osnoise,timerlat}_{top,hist} At least in glibc, getopt_long() increments its internal nextchar variable even if the option is not recognized. That means that in the case of "-p100", common_parse_options() sets nextchar pointing to '1', and timerlat_hist_parse_args() sees '1', not 'p'; the same then repeats for the first and second '0'. As there is no way to restore the correct internal state of getopt_long() reliably, fix the issue by merging the common options back to the longopt array and option string of the [tool]_parse_args() functions using a macro; only the switch part is left in the original function, which is renamed to set_common_option(). Fixes: 850cd24cb6d6 ("tools/rtla: Add common_parse_options()") Reported-by: John Kacur Tested-by: John Kacur Link: https://lore.kernel.org/r/20260602125506.3325345-1-tglozar@redhat.com Signed-off-by: Tomas Glozar diff --git a/tools/tracing/rtla/src/common.c b/tools/tracing/rtla/src/common.c index 35e3d3aa922e..bc9d01ddd102 100644 --- a/tools/tracing/rtla/src/common.c +++ b/tools/tracing/rtla/src/common.c @@ -84,37 +84,20 @@ int getopt_auto(int argc, char **argv, const struct option *long_opts) } /* - * common_parse_options - parse common command line options + * set_common_option - set common options * + * @c: option character * @argc: argument count * @argv: argument vector * @common: common parameters structure * * Parse command line options that are common to all rtla tools. * - * Returns: non zero if a common option was parsed, or 0 - * if the option should be handled by tool-specific parsing. + * Returns: 1 if the option was set, 0 otherwise. */ -int common_parse_options(int argc, char **argv, struct common_params *common) +int set_common_option(int c, int argc, char **argv, struct common_params *common) { struct trace_events *tevent; - int saved_state = optind; - int c; - - static struct option long_options[] = { - {"cpus", required_argument, 0, 'c'}, - {"cgroup", optional_argument, 0, 'C'}, - {"debug", no_argument, 0, 'D'}, - {"duration", required_argument, 0, 'd'}, - {"event", required_argument, 0, 'e'}, - {"house-keeping", required_argument, 0, 'H'}, - {"priority", required_argument, 0, 'P'}, - {0, 0, 0, 0} - }; - - opterr = 0; - c = getopt_auto(argc, argv, long_options); - opterr = 1; switch (c) { case 'c': @@ -154,11 +137,10 @@ int common_parse_options(int argc, char **argv, struct common_params *common) common->set_sched = 1; break; default: - optind = saved_state; return 0; } - return c; + return 1; } /* diff --git a/tools/tracing/rtla/src/common.h b/tools/tracing/rtla/src/common.h index 51665db4ffce..8921807bda98 100644 --- a/tools/tracing/rtla/src/common.h +++ b/tools/tracing/rtla/src/common.h @@ -178,7 +178,17 @@ int osnoise_set_stop_total_us(struct osnoise_context *context, long long stop_total_us); int getopt_auto(int argc, char **argv, const struct option *long_opts); -int common_parse_options(int argc, char **argv, struct common_params *common); + +#define COMMON_OPTIONS \ + {"cpus", required_argument, 0, 'c'},\ + {"cgroup", optional_argument, 0, 'C'},\ + {"debug", no_argument, 0, 'D'},\ + {"duration", required_argument, 0, 'd'},\ + {"event", required_argument, 0, 'e'},\ + {"house-keeping", required_argument, 0, 'H'},\ + {"priority", required_argument, 0, 'P'} +int set_common_option(int c, int argc, char **argv, struct common_params *common); + int common_apply_config(struct osnoise_tool *tool, struct common_params *params); int top_main_loop(struct osnoise_tool *tool); int hist_main_loop(struct osnoise_tool *tool); diff --git a/tools/tracing/rtla/src/osnoise_hist.c b/tools/tracing/rtla/src/osnoise_hist.c index 8ad816b80265..cb4ce58c5987 100644 --- a/tools/tracing/rtla/src/osnoise_hist.c +++ b/tools/tracing/rtla/src/osnoise_hist.c @@ -475,6 +475,7 @@ static struct common_params while (1) { static struct option long_options[] = { + COMMON_OPTIONS, {"auto", required_argument, 0, 'a'}, {"bucket-size", required_argument, 0, 'b'}, {"entries", required_argument, 0, 'E'}, @@ -498,15 +499,15 @@ static struct common_params {0, 0, 0, 0} }; - if (common_parse_options(argc, argv, ¶ms->common)) - continue; - c = getopt_auto(argc, argv, long_options); /* detect the end of the options. */ if (c == -1) break; + if (set_common_option(c, argc, argv, ¶ms->common)) + continue; + switch (c) { case 'a': /* set sample stop to auto_thresh */ diff --git a/tools/tracing/rtla/src/osnoise_top.c b/tools/tracing/rtla/src/osnoise_top.c index 244bdce022ad..e65312ec26c4 100644 --- a/tools/tracing/rtla/src/osnoise_top.c +++ b/tools/tracing/rtla/src/osnoise_top.c @@ -328,6 +328,7 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv) while (1) { static struct option long_options[] = { + COMMON_OPTIONS, {"auto", required_argument, 0, 'a'}, {"help", no_argument, 0, 'h'}, {"period", required_argument, 0, 'p'}, @@ -346,15 +347,15 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv) {0, 0, 0, 0} }; - if (common_parse_options(argc, argv, ¶ms->common)) - continue; - c = getopt_auto(argc, argv, long_options); /* Detect the end of the options. */ if (c == -1) break; + if (set_common_option(c, argc, argv, ¶ms->common)) + continue; + switch (c) { case 'a': /* set sample stop to auto_thresh */ diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/src/timerlat_hist.c index 79142af4f566..4b6708e333b8 100644 --- a/tools/tracing/rtla/src/timerlat_hist.c +++ b/tools/tracing/rtla/src/timerlat_hist.c @@ -785,6 +785,7 @@ static struct common_params while (1) { static struct option long_options[] = { + COMMON_OPTIONS, {"auto", required_argument, 0, 'a'}, {"bucket-size", required_argument, 0, 'b'}, {"entries", required_argument, 0, 'E'}, @@ -819,11 +820,11 @@ static struct common_params {0, 0, 0, 0} }; - if (common_parse_options(argc, argv, ¶ms->common)) - continue; - c = getopt_auto(argc, argv, long_options); + if (set_common_option(c, argc, argv, ¶ms->common)) + continue; + /* detect the end of the options. */ if (c == -1) break; diff --git a/tools/tracing/rtla/src/timerlat_top.c b/tools/tracing/rtla/src/timerlat_top.c index 64cbdcc878b0..91f88bbebad9 100644 --- a/tools/tracing/rtla/src/timerlat_top.c +++ b/tools/tracing/rtla/src/timerlat_top.c @@ -549,6 +549,7 @@ static struct common_params while (1) { static struct option long_options[] = { + COMMON_OPTIONS, {"auto", required_argument, 0, 'a'}, {"help", no_argument, 0, 'h'}, {"irq", required_argument, 0, 'i'}, @@ -577,11 +578,11 @@ static struct common_params {0, 0, 0, 0} }; - if (common_parse_options(argc, argv, ¶ms->common)) - continue; - c = getopt_auto(argc, argv, long_options); + if (set_common_option(c, argc, argv, ¶ms->common)) + continue; + /* detect the end of the options. */ if (c == -1) break;