Linux Trace Kernel
 help / color / mirror / Atom feed
* [PATCH 1/4] rtla: Allow unsetting non-list custom-callback CLI options
@ 2026-06-29  8:36 Tomas Glozar
  2026-06-29  8:36 ` [PATCH 2/4] rtla: Add unit tests for unset in opt callbacks Tomas Glozar
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Tomas Glozar @ 2026-06-29  8:36 UTC (permalink / raw)
  To: Steven Rostedt, Tomas Glozar
  Cc: John Kacur, Luis Goncalves, Crystal Wood, Costa Shulyupin,
	Wander Lairson Costa, LKML, linux-trace-kernel

libsubcmd implicitly allows the user to unset already set options using
a "no-" prefix for long options. For example, if I set the period like
this:

$ rtla timerlat -D
Loading BPF program
reading osnoise/timerlat_period_us returned 1000
setting osnoise/timerlat_period_us to 1000
reading osnoise/print_stack returned 0
setting osnoise/print_stack to 0
...
<timerlat top>

it can be unset by a subsequent --no-debug:

$ rtla timerlat -D --no-debug
...
<timerlat top>

Currently, this works only for boolean options. Extend the feature for
all options by implementing handling of the "unset" argument in opt_*()
callbacks defined in cli_p.h, except for list options, i.e. options that
can be passed multiple times (--event, --filter, --trigger,
--on-threshold, --on-end).

This allows, for example, unsetting of int/long long options, e.g. "-p":

$ rtla timerlat -D -p100 --no-period
...
setting osnoise/timerlat_period_us to 1000
...

By default, options in params struct are reset to zero. A constant is
added for every parameter with a different default value, which is then
used both in <tool>_hist_args() while setting the initial value and in
opt_*() when unsetting the option. This refactoring ensures there is no
duplicate "magic number".

The default value for opt_llong_callback() and opt_int_callback() is
passed in struct option's defval field; new macros
RTLA_OPT_{LLONG,INT}{,_DEFVAL} are added to define the field
conveniently. The default value for other callbacks is hardcoded inside
each callback's unset logic.

Signed-off-by: Tomas Glozar <tglozar@redhat.com>
---
 tools/tracing/rtla/src/cli.c   |  42 +++----
 tools/tracing/rtla/src/cli_p.h | 219 +++++++++++++++++++++++++++------
 2 files changed, 194 insertions(+), 67 deletions(-)

diff --git a/tools/tracing/rtla/src/cli.c b/tools/tracing/rtla/src/cli.c
index c5279c9875310..fb8c972c0746b 100644
--- a/tools/tracing/rtla/src/cli.c
+++ b/tools/tracing/rtla/src/cli.c
@@ -192,10 +192,10 @@ struct common_params *osnoise_hist_parse_args(int argc, char **argv)
 	actions_init(&params->common.threshold_actions);
 	actions_init(&params->common.end_actions);
 
-	/* display data in microseconds */
-	params->common.output_divisor = 1000;
-	params->common.hist.bucket_size = 1;
-	params->common.hist.entries = 256;
+	/* set default values */
+	params->common.output_divisor = default_output_divisor;
+	params->common.hist.bucket_size = default_bucket_size;
+	params->common.hist.entries = default_entries;
 
 	argc = parse_options(argc, (const char **)argv,
 			     osnoise_hist_options, osnoise_hist_usage,
@@ -280,19 +280,15 @@ struct common_params *timerlat_top_parse_args(int argc, char **argv)
 	actions_init(&params->common.threshold_actions);
 	actions_init(&params->common.end_actions);
 
-	/* disabled by default */
-	params->dma_latency = -1;
-	params->deepest_idle_state = -2;
-
-	/* display data in microseconds */
-	params->common.output_divisor = 1000;
+	/* set default values */
+	params->dma_latency = default_dma_latency;
+	params->deepest_idle_state = default_deepest_idle_state;
+	params->common.output_divisor = default_output_divisor;
+	params->stack_format = default_stack_format;
 
 	/* default to BPF mode */
 	params->mode = TRACING_MODE_BPF;
 
-	/* default to truncate stack format */
-	params->stack_format = STACK_FORMAT_TRUNCATE;
-
 	argc = parse_options(argc, (const char **)argv,
 			     timerlat_top_options, timerlat_top_usage,
 			     common_parse_options_flags);
@@ -403,23 +399,17 @@ struct common_params *timerlat_hist_parse_args(int argc, char **argv)
 	actions_init(&params->common.threshold_actions);
 	actions_init(&params->common.end_actions);
 
-	/* disabled by default */
-	params->dma_latency = -1;
-
-	/* disabled by default */
-	params->deepest_idle_state = -2;
-
-	/* display data in microseconds */
-	params->common.output_divisor = 1000;
-	params->common.hist.bucket_size = 1;
-	params->common.hist.entries = 256;
+	/* set default values */
+	params->dma_latency = default_dma_latency;
+	params->deepest_idle_state = default_deepest_idle_state;
+	params->common.output_divisor = default_output_divisor;
+	params->common.hist.bucket_size = default_bucket_size;
+	params->common.hist.entries = default_entries;
+	params->stack_format = default_stack_format;
 
 	/* default to BPF mode */
 	params->mode = TRACING_MODE_BPF;
 
-	/* default to truncate stack format */
-	params->stack_format = STACK_FORMAT_TRUNCATE;
-
 	argc = parse_options(argc, (const char **)argv,
 			     timerlat_hist_options, timerlat_hist_usage,
 			     common_parse_options_flags);
diff --git a/tools/tracing/rtla/src/cli_p.h b/tools/tracing/rtla/src/cli_p.h
index 3c939de9abf02..3a93dba60215b 100644
--- a/tools/tracing/rtla/src/cli_p.h
+++ b/tools/tracing/rtla/src/cli_p.h
@@ -22,6 +22,38 @@ struct timerlat_cb_data {
 	char *trace_output;
 };
 
+/*
+ * Non-zero default values for parameters
+ */
+static const int default_dma_latency = -1; /* -1 = unset */
+static const int default_deepest_idle_state = -2; /* -1 = disable all, -2 = unset */
+static const int default_output_divisor = 1000;
+static const int default_bucket_size = 1;
+static const int default_entries = 256;
+static const enum stack_format default_stack_format = STACK_FORMAT_TRUNCATE;
+
+/*
+ * Shorthand macros for integer/long long command line options using
+ * opt_int_callback/opt_llong_callback, with variants that set defval.
+ *
+ * Note: defval's type is intptr_t. opt_int_callback interprets it directly as
+ * an int, opt_llong_callback interprets it as a pointer to a long long, as
+ * long long does not fit into intptr_t on 32-bit architectures.
+ */
+#define RTLA_OPT_LLONG(s, l, v, a, h) \
+	OPT_CALLBACK(s, l, v, a, h, opt_llong_callback)
+
+#define RTLA_OPT_LLONG_DEFVAL(s, l, v, a, h, d) { .type = OPTION_CALLBACK, \
+	.short_name = (s), .long_name = (l), .value = (v), .argh = (a), \
+	.help = (h), .callback = opt_llong_callback, .defval = (intptr_t)(d) }
+
+#define RTLA_OPT_INT(s, l, v, a, h) \
+	OPT_CALLBACK(s, l, v, a, h, opt_int_callback)
+
+#define RTLA_OPT_INT_DEFVAL(s, l, v, a, h, d) { .type = OPTION_CALLBACK, \
+	.short_name = (s), .long_name = (l), .value = (v), .argh = (a), \
+	.help = (h), .callback = opt_int_callback, .defval = (intptr_t)(d) }
+
 /*
  * Macros for command line options common to all tools
  *
@@ -108,14 +140,12 @@ struct timerlat_cb_data {
 #define RTLA_OPT_QUIET OPT_BOOLEAN('q', "quiet", &params->common.quiet, \
 	"print only a summary at the end")
 
-#define RTLA_OPT_TRACE_BUFFER_SIZE OPT_CALLBACK(0, "trace-buffer-size", \
+#define RTLA_OPT_TRACE_BUFFER_SIZE RTLA_OPT_INT(0, "trace-buffer-size", \
 	&params->common.buffer_size, "kB", \
-	"set the per-cpu trace buffer size in kB", \
-	opt_int_callback)
+	"set the per-cpu trace buffer size in kB")
 
-#define RTLA_OPT_WARM_UP OPT_CALLBACK(0, "warm-up", &params->common.warmup, "s", \
-	"let the workload run for s seconds before collecting data", \
-	opt_int_callback)
+#define RTLA_OPT_WARM_UP RTLA_OPT_INT(0, "warm-up", &params->common.warmup, "s", \
+	"let the workload run for s seconds before collecting data")
 
 #define RTLA_OPT_AUTO(cb) OPT_CALLBACK('a', "auto", &cb_data, "us", \
 	"set automatic trace mode, stopping the session if argument in us sample is hit", \
@@ -143,7 +173,12 @@ static int opt_llong_callback(const struct option *opt, const char *arg, int uns
 {
 	long long *value = opt->value;
 
-	if (unset || !arg)
+	if (unset) {
+		*value = opt->defval ? *(long long *)opt->defval : 0;
+		return 0;
+	}
+
+	if (!arg)
 		return -1;
 
 	*value = get_llong_from_str((char *)arg);
@@ -154,7 +189,12 @@ static int opt_int_callback(const struct option *opt, const char *arg, int unset
 {
 	int *value = opt->value;
 
-	if (unset || !arg)
+	if (unset) {
+		*value = (int)opt->defval;
+		return 0;
+	}
+
+	if (!arg)
 		return -1;
 
 	if (strtoi(arg, value))
@@ -168,7 +208,13 @@ static int opt_cpus_cb(const struct option *opt, const char *arg, int unset)
 	struct common_params *params = opt->value;
 	int retval;
 
-	if (unset || !arg)
+	if (unset) {
+		CPU_ZERO(&params->monitored_cpus);
+		params->cpus = NULL;
+		return 0;
+	}
+
+	if (!arg)
 		return -1;
 
 	retval = parse_cpu_set((char *)arg, &params->monitored_cpus);
@@ -183,8 +229,11 @@ static int opt_cgroup_cb(const struct option *opt, const char *arg, int unset)
 {
 	struct common_params *params = opt->value;
 
-	if (unset)
-		return -1;
+	if (unset) {
+		params->cgroup = 0;
+		params->cgroup_name = NULL;
+		return 0;
+	}
 
 	params->cgroup = 1;
 	params->cgroup_name = (char *)arg;
@@ -199,7 +248,12 @@ static int opt_duration_cb(const struct option *opt, const char *arg, int unset)
 {
 	struct common_params *params = opt->value;
 
-	if (unset || !arg)
+	if (unset) {
+		params->duration = 0;
+		return 0;
+	}
+
+	if (!arg)
 		return -1;
 
 	params->duration = parse_seconds_duration((char *)arg);
@@ -233,7 +287,13 @@ static int opt_housekeeping_cb(const struct option *opt, const char *arg, int un
 	struct common_params *params = opt->value;
 	int retval;
 
-	if (unset || !arg)
+	if (unset) {
+		params->hk_cpus = 0;
+		CPU_ZERO(&params->hk_cpu_set);
+		return 0;
+	}
+
+	if (!arg)
 		return -1;
 
 	params->hk_cpus = 1;
@@ -249,7 +309,13 @@ static int opt_priority_cb(const struct option *opt, const char *arg, int unset)
 	struct common_params *params = opt->value;
 	int retval;
 
-	if (unset || !arg)
+	if (unset) {
+		memset(&params->sched_param, 0, sizeof(params->sched_param));
+		params->set_sched = 0;
+		return 0;
+	}
+
+	if (!arg)
 		return -1;
 
 	retval = parse_prio((char *)arg, &params->sched_param);
@@ -301,9 +367,8 @@ static int opt_filter_cb(const struct option *opt, const char *arg, int unset)
 	"osnoise runtime in us", \
 	opt_osnoise_runtime_cb)
 
-#define OSNOISE_OPT_THRESHOLD OPT_CALLBACK('T', "threshold", &params->threshold, "us", \
-	"the minimum delta to be considered a noise", \
-	opt_llong_callback)
+#define OSNOISE_OPT_THRESHOLD RTLA_OPT_LLONG('T', "threshold", &params->threshold, "us", \
+	"the minimum delta to be considered a noise")
 
 /*
  * Callback functions for command line options for osnoise tools
@@ -315,7 +380,14 @@ static int opt_osnoise_auto_cb(const struct option *opt, const char *arg, int un
 	struct osnoise_params *params = cb_data->params;
 	long long auto_thresh;
 
-	if (unset || !arg)
+	if (unset) {
+		params->common.stop_us = 0;
+		params->threshold = 0;
+		cb_data->trace_output = NULL;
+		return 0;
+	}
+
+	if (!arg)
 		return -1;
 
 	auto_thresh = get_llong_from_str((char *)arg);
@@ -332,7 +404,12 @@ static int opt_osnoise_period_cb(const struct option *opt, const char *arg, int
 {
 	unsigned long long *period = opt->value;
 
-	if (unset || !arg)
+	if (unset) {
+		*period = 0;
+		return 0;
+	}
+
+	if (!arg)
 		return -1;
 
 	*period = get_llong_from_str((char *)arg);
@@ -346,7 +423,12 @@ static int opt_osnoise_runtime_cb(const struct option *opt, const char *arg, int
 {
 	unsigned long long *runtime = opt->value;
 
-	if (unset || !arg)
+	if (unset) {
+		*runtime = 0;
+		return 0;
+	}
+
+	if (!arg)
 		return -1;
 
 	*runtime = get_llong_from_str((char *)arg);
@@ -360,8 +442,10 @@ static int opt_osnoise_trace_output_cb(const struct option *opt, const char *arg
 {
 	const char **trace_output = opt->value;
 
-	if (unset)
-		return -1;
+	if (unset) {
+		*trace_output = NULL;
+		return 0;
+	}
 
 	if (!arg) {
 		*trace_output = "osnoise_trace.txt";
@@ -412,9 +496,8 @@ static int opt_osnoise_on_end_cb(const struct option *opt, const char *arg, int
 	"timerlat period in us", \
 	opt_timerlat_period_cb)
 
-#define TIMERLAT_OPT_STACK OPT_CALLBACK('s', "stack", &params->print_stack, "us", \
-	"save the stack trace at the IRQ if a thread latency is higher than the argument in us", \
-	opt_llong_callback)
+#define TIMERLAT_OPT_STACK RTLA_OPT_LLONG('s', "stack", &params->print_stack, "us", \
+	"save the stack trace at the IRQ if a thread latency is higher than the argument in us")
 
 #define TIMERLAT_OPT_NANO OPT_CALLBACK_NOOPT('n', "nano", params, NULL, \
 	"display data in nanoseconds", \
@@ -424,10 +507,10 @@ static int opt_osnoise_on_end_cb(const struct option *opt, const char *arg, int
 	"set /dev/cpu_dma_latency latency <us> to reduce exit from idle latency", \
 	opt_dma_latency_cb)
 
-#define TIMERLAT_OPT_DEEPEST_IDLE_STATE OPT_CALLBACK(0, "deepest-idle-state", \
+#define TIMERLAT_OPT_DEEPEST_IDLE_STATE RTLA_OPT_INT_DEFVAL(0, "deepest-idle-state", \
 	&params->deepest_idle_state, "n", \
 	"only go down to idle state n on cpus used by timerlat to reduce exit from idle latency", \
-	opt_int_callback)
+	default_deepest_idle_state)
 
 #define TIMERLAT_OPT_AA_ONLY OPT_CALLBACK(0, "aa-only", params, "us", \
 	"stop if <us> latency is hit, only printing the auto analysis (reduces CPU usage)", \
@@ -459,7 +542,12 @@ static int opt_timerlat_period_cb(const struct option *opt, const char *arg, int
 {
 	long long *period = opt->value;
 
-	if (unset || !arg)
+	if (unset) {
+		*period = 0;
+		return 0;
+	}
+
+	if (!arg)
 		return -1;
 
 	*period = get_llong_from_str((char *)arg);
@@ -475,7 +563,15 @@ static int opt_timerlat_auto_cb(const struct option *opt, const char *arg, int u
 	struct timerlat_params *params = cb_data->params;
 	long long auto_thresh;
 
-	if (unset || !arg)
+	if (unset) {
+		params->common.stop_total_us = 0;
+		params->common.stop_us = 0;
+		params->print_stack = 0;
+		cb_data->trace_output = NULL;
+		return 0;
+	}
+
+	if (!arg)
 		return -1;
 
 	auto_thresh = get_llong_from_str((char *)arg);
@@ -494,7 +590,12 @@ static int opt_dma_latency_cb(const struct option *opt, const char *arg, int uns
 	int *dma_latency = opt->value;
 	int retval;
 
-	if (unset || !arg)
+	if (unset) {
+		*dma_latency = default_dma_latency;
+		return 0;
+	}
+
+	if (!arg)
 		return -1;
 
 	retval = strtoi((char *)arg, dma_latency);
@@ -511,7 +612,15 @@ static int opt_aa_only_cb(const struct option *opt, const char *arg, int unset)
 	struct timerlat_params *params = opt->value;
 	long long auto_thresh;
 
-	if (unset || !arg)
+	if (unset) {
+		params->common.stop_total_us = 0;
+		params->common.stop_us = 0;
+		params->print_stack = 0;
+		params->common.aa_only = 0;
+		return 0;
+	}
+
+	if (!arg)
 		return -1;
 
 	auto_thresh = get_llong_from_str((char *)arg);
@@ -527,8 +636,10 @@ static int opt_timerlat_trace_output_cb(const struct option *opt, const char *ar
 {
 	const char **trace_output = opt->value;
 
-	if (unset)
-		return -1;
+	if (unset) {
+		*trace_output = NULL;
+		return 0;
+	}
 
 	if (!arg) {
 		*trace_output = "timerlat_trace.txt";
@@ -576,8 +687,11 @@ static int opt_user_threads_cb(const struct option *opt, const char *arg, int un
 {
 	struct timerlat_params *params = opt->value;
 
-	if (unset)
-		return -1;
+	if (unset) {
+		params->common.user_workload = false;
+		params->common.user_data = false;
+		return 0;
+	}
 
 	params->common.user_workload = true;
 	params->common.user_data = true;
@@ -589,8 +703,10 @@ static int opt_nano_cb(const struct option *opt, const char *arg, int unset)
 {
 	struct timerlat_params *params = opt->value;
 
-	if (unset)
-		return -1;
+	if (unset) {
+		params->common.output_divisor = default_output_divisor;
+		return 0;
+	}
 
 	params->common.output_divisor = 1;
 
@@ -601,7 +717,12 @@ static int opt_stack_format_cb(const struct option *opt, const char *arg, int un
 {
 	int *format = opt->value;
 
-	if (unset || !arg)
+	if (unset) {
+		*format = default_stack_format;
+		return 0;
+	}
+
+	if (!arg)
 		return -1;
 
 	*format = parse_stack_format((char *)arg);
@@ -616,7 +737,13 @@ static int opt_timerlat_align_cb(const struct option *opt, const char *arg, int
 {
 	struct timerlat_params *params = opt->value;
 
-	if (unset || !arg)
+	if (unset) {
+		params->timerlat_align = false;
+		params->timerlat_align_us = 0;
+		return 0;
+	}
+
+	if (!arg)
 		return -1;
 
 	params->timerlat_align = true;
@@ -662,7 +789,12 @@ static int opt_bucket_size_cb(const struct option *opt, const char *arg, int uns
 {
 	int *bucket_size = opt->value;
 
-	if (unset || !arg)
+	if (unset) {
+		*bucket_size = default_bucket_size;
+		return 0;
+	}
+
+	if (!arg)
 		return -1;
 
 	*bucket_size = get_llong_from_str((char *)arg);
@@ -676,7 +808,12 @@ static int opt_entries_cb(const struct option *opt, const char *arg, int unset)
 {
 	int *entries = opt->value;
 
-	if (unset || !arg)
+	if (unset) {
+		*entries = default_entries;
+		return 0;
+	}
+
+	if (!arg)
 		return -1;
 
 	*entries = get_llong_from_str((char *)arg);
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/4] rtla: Add unit tests for unset in opt callbacks
  2026-06-29  8:36 [PATCH 1/4] rtla: Allow unsetting non-list custom-callback CLI options Tomas Glozar
@ 2026-06-29  8:36 ` Tomas Glozar
  2026-06-29  8:36 ` [PATCH 3/4] rtla: Add unit tests for CLI with unset Tomas Glozar
  2026-06-29  8:36 ` [PATCH 4/4] Documentation/rtla: Document unsetting options Tomas Glozar
  2 siblings, 0 replies; 4+ messages in thread
From: Tomas Glozar @ 2026-06-29  8:36 UTC (permalink / raw)
  To: Steven Rostedt, Tomas Glozar
  Cc: John Kacur, Luis Goncalves, Crystal Wood, Costa Shulyupin,
	Wander Lairson Costa, LKML, linux-trace-kernel

Test for each opt callback that implements the unset option whether the
option sets the specified default value back correctly.

Signed-off-by: Tomas Glozar <tglozar@redhat.com>
---
 .../rtla/tests/unit/cli_opt_callback.c        | 295 ++++++++++++++++++
 1 file changed, 295 insertions(+)

diff --git a/tools/tracing/rtla/tests/unit/cli_opt_callback.c b/tools/tracing/rtla/tests/unit/cli_opt_callback.c
index 4a406af42821b..413a04f898fbb 100644
--- a/tools/tracing/rtla/tests/unit/cli_opt_callback.c
+++ b/tools/tracing/rtla/tests/unit/cli_opt_callback.c
@@ -40,6 +40,30 @@ START_TEST(test_opt_llong_callback_min)
 }
 END_TEST
 
+START_TEST(test_opt_llong_callback_unset)
+{
+	long long test_value = 0;
+	const struct option opt = TEST_CALLBACK(&test_value, opt_llong_callback);
+
+	ck_assert_int_eq(opt_llong_callback(&opt, "1234567890", 0), 0);
+	ck_assert_int_eq(opt_llong_callback(&opt, NULL, 1), 0);
+	ck_assert_int_eq(test_value, 0);
+}
+END_TEST
+
+START_TEST(test_opt_llong_callback_unset_defval)
+{
+	long long test_value = 0;
+	const long long default_value = 42;
+	const struct option opt = RTLA_OPT_LLONG_DEFVAL('t', "test", &test_value, "test value",
+							"test help", &default_value);
+
+	ck_assert_int_eq(opt_llong_callback(&opt, "1234567890", 0), 0);
+	ck_assert_int_eq(opt_llong_callback(&opt, NULL, 1), 0);
+	ck_assert_int_eq(test_value, default_value);
+}
+END_TEST
+
 START_TEST(test_opt_int_callback_simple)
 {
 	int test_value = 0;
@@ -90,6 +114,29 @@ START_TEST(test_opt_int_callback_non_numeric_suffix)
 }
 END_TEST
 
+START_TEST(test_opt_int_callback_unset)
+{
+	int test_value = 0;
+	const struct option opt = TEST_CALLBACK(&test_value, opt_int_callback);
+
+	ck_assert_int_eq(opt_int_callback(&opt, "1234567890", 0), 0);
+	ck_assert_int_eq(opt_int_callback(&opt, NULL, 1), 0);
+	ck_assert_int_eq(test_value, 0);
+}
+END_TEST
+
+START_TEST(test_opt_int_callback_unset_defval)
+{
+	int test_value = 0;
+	const struct option opt = RTLA_OPT_INT_DEFVAL('t', "test", &test_value, "test value",
+						      "test help", 42);
+
+	ck_assert_int_eq(opt_int_callback(&opt, "1234567890", 0), 0);
+	ck_assert_int_eq(opt_int_callback(&opt, NULL, 1), 0);
+	ck_assert_int_eq(test_value, 42);
+}
+END_TEST
+
 START_TEST(test_opt_cpus_cb)
 {
 	struct common_params params = {0};
@@ -134,6 +181,18 @@ START_TEST(test_opt_cgroup_cb_equals)
 }
 END_TEST
 
+START_TEST(test_opt_cgroup_cb_unset)
+{
+	struct common_params params = {0};
+	const struct option opt = TEST_CALLBACK(&params, opt_cgroup_cb);
+
+	ck_assert_int_eq(opt_cgroup_cb(&opt, "cgroup", 0), 0);
+	ck_assert_int_eq(opt_cgroup_cb(&opt, NULL, 1), 0);
+	ck_assert_int_eq(params.cgroup, 0);
+	ck_assert_ptr_null(params.cgroup_name);
+}
+END_TEST
+
 START_TEST(test_opt_duration_cb)
 {
 	struct common_params params = {0};
@@ -154,6 +213,17 @@ START_TEST(test_opt_duration_cb_invalid)
 }
 END_TEST
 
+START_TEST(test_opt_duration_cb_unset)
+{
+	struct common_params params = {0};
+	const struct option opt = TEST_CALLBACK(&params, opt_duration_cb);
+
+	ck_assert_int_eq(opt_duration_cb(&opt, "1m", 0), 0);
+	ck_assert_int_eq(opt_duration_cb(&opt, NULL, 1), 0);
+	ck_assert_int_eq(params.duration, 0);
+}
+END_TEST
+
 START_TEST(test_opt_event_cb)
 {
 	struct trace_events *events = NULL;
@@ -205,6 +275,19 @@ START_TEST(test_opt_housekeeping_cb_invalid)
 }
 END_TEST
 
+START_TEST(test_opt_housekeeping_cb_unset)
+{
+	struct common_params params = {0};
+	const struct option opt = TEST_CALLBACK(&params, opt_housekeeping_cb);
+
+	nr_cpus = 4;
+	ck_assert_int_eq(opt_housekeeping_cb(&opt, "0-3", 0), 0);
+	ck_assert_int_eq(opt_housekeeping_cb(&opt, NULL, 1), 0);
+	ck_assert_int_eq(params.hk_cpus, 0);
+	ck_assert_int_eq(CPU_COUNT(&params.hk_cpu_set), 0);
+}
+END_TEST
+
 START_TEST(test_opt_priority_cb)
 {
 	struct common_params params = {0};
@@ -226,6 +309,18 @@ START_TEST(test_opt_priority_cb_invalid)
 }
 END_TEST
 
+START_TEST(test_opt_priority_cb_unset)
+{
+	struct common_params params = {0};
+	const struct option opt = TEST_CALLBACK(&params, opt_priority_cb);
+
+	ck_assert_int_eq(opt_priority_cb(&opt, "f:95", 0), 0);
+	ck_assert_int_eq(opt_priority_cb(&opt, NULL, 1), 0);
+	ck_assert_int_eq(params.sched_param.sched_policy, 0);
+	ck_assert_int_eq(params.sched_param.sched_priority, 0);
+}
+END_TEST
+
 START_TEST(test_opt_trigger_cb)
 {
 	struct trace_events *events = trace_event_alloc("sched:sched_switch");
@@ -279,6 +374,20 @@ START_TEST(test_opt_osnoise_auto_cb)
 }
 END_TEST
 
+START_TEST(test_opt_osnoise_auto_cb_unset)
+{
+	struct osnoise_params params = {0};
+	struct osnoise_cb_data cb_data = {&params};
+	const struct option opt = TEST_CALLBACK(&cb_data, opt_osnoise_auto_cb);
+
+	ck_assert_int_eq(opt_osnoise_auto_cb(&opt, "10", 0), 0);
+	ck_assert_int_eq(opt_osnoise_auto_cb(&opt, NULL, 1), 0);
+	ck_assert_int_eq(params.common.stop_us, 0);
+	ck_assert_int_eq(params.threshold, 0);
+	ck_assert_ptr_null(cb_data.trace_output);
+}
+END_TEST
+
 START_TEST(test_opt_osnoise_period_cb)
 {
 	unsigned long long period = 0;
@@ -299,6 +408,17 @@ START_TEST(test_opt_osnoise_period_cb_invalid)
 }
 END_TEST
 
+START_TEST(test_opt_osnoise_period_cb_unset)
+{
+	unsigned long long period = 0;
+	const struct option opt = TEST_CALLBACK(&period, opt_osnoise_period_cb);
+
+	ck_assert_int_eq(opt_osnoise_period_cb(&opt, "1000000", 0), 0);
+	ck_assert_int_eq(opt_osnoise_period_cb(&opt, NULL, 1), 0);
+	ck_assert_int_eq(period, 0);
+}
+END_TEST
+
 START_TEST(test_opt_osnoise_runtime_cb)
 {
 	unsigned long long runtime = 0;
@@ -319,6 +439,17 @@ START_TEST(test_opt_osnoise_runtime_cb_invalid)
 }
 END_TEST
 
+START_TEST(test_opt_osnoise_runtime_cb_unset)
+{
+	unsigned long long runtime = 0;
+	const struct option opt = TEST_CALLBACK(&runtime, opt_osnoise_runtime_cb);
+
+	ck_assert_int_eq(opt_osnoise_runtime_cb(&opt, "900000", 0), 0);
+	ck_assert_int_eq(opt_osnoise_runtime_cb(&opt, NULL, 1), 0);
+	ck_assert_int_eq(runtime, 0);
+}
+END_TEST
+
 START_TEST(test_opt_osnoise_trace_output_cb)
 {
 	const char *trace_output = NULL;
@@ -339,6 +470,17 @@ START_TEST(test_opt_osnoise_trace_output_cb_noarg)
 }
 END_TEST
 
+START_TEST(test_opt_osnoise_trace_output_cb_unset)
+{
+	const char *trace_output = NULL;
+	const struct option opt = TEST_CALLBACK(&trace_output, opt_osnoise_trace_output_cb);
+
+	ck_assert_int_eq(opt_osnoise_trace_output_cb(&opt, "trace.txt", 0), 0);
+	ck_assert_int_eq(opt_osnoise_trace_output_cb(&opt, NULL, 1), 0);
+	ck_assert_ptr_null(trace_output);
+}
+END_TEST
+
 START_TEST(test_opt_osnoise_on_threshold_cb)
 {
 	struct actions actions = {0};
@@ -403,6 +545,17 @@ START_TEST(test_opt_timerlat_period_cb_invalid)
 }
 END_TEST
 
+START_TEST(test_opt_timerlat_period_cb_unset)
+{
+	long long period = 0;
+	const struct option opt = TEST_CALLBACK(&period, opt_timerlat_period_cb);
+
+	ck_assert_int_eq(opt_timerlat_period_cb(&opt, "1000", 0), 0);
+	ck_assert_int_eq(opt_timerlat_period_cb(&opt, NULL, 1), 0);
+	ck_assert_int_eq(period, 0);
+}
+END_TEST
+
 START_TEST(test_opt_timerlat_auto_cb)
 {
 	struct timerlat_params params = {0};
@@ -417,6 +570,21 @@ START_TEST(test_opt_timerlat_auto_cb)
 }
 END_TEST
 
+START_TEST(test_opt_timerlat_auto_cb_unset)
+{
+	struct timerlat_params params = {0};
+	struct timerlat_cb_data cb_data = {&params};
+	const struct option opt = TEST_CALLBACK(&cb_data, opt_timerlat_auto_cb);
+
+	ck_assert_int_eq(opt_timerlat_auto_cb(&opt, "10", 0), 0);
+	ck_assert_int_eq(opt_timerlat_auto_cb(&opt, NULL, 1), 0);
+	ck_assert_int_eq(params.common.stop_us, 0);
+	ck_assert_int_eq(params.common.stop_total_us, 0);
+	ck_assert_int_eq(params.print_stack, 0);
+	ck_assert_ptr_null(cb_data.trace_output);
+}
+END_TEST
+
 START_TEST(test_opt_dma_latency_cb)
 {
 	int dma_latency = 0;
@@ -447,6 +615,17 @@ START_TEST(test_opt_dma_latency_cb_max)
 }
 END_TEST
 
+START_TEST(test_opt_dma_latency_cb_unset)
+{
+	int dma_latency = 0;
+	const struct option opt = TEST_CALLBACK(&dma_latency, opt_dma_latency_cb);
+
+	ck_assert_int_eq(opt_dma_latency_cb(&opt, "1000", 0), 0);
+	ck_assert_int_eq(opt_dma_latency_cb(&opt, NULL, 1), 0);
+	ck_assert_int_eq(dma_latency, default_dma_latency);
+}
+END_TEST
+
 START_TEST(test_opt_aa_only_cb)
 {
 	struct timerlat_params params = {0};
@@ -460,6 +639,20 @@ START_TEST(test_opt_aa_only_cb)
 }
 END_TEST
 
+START_TEST(test_opt_aa_only_cb_unset)
+{
+	struct timerlat_params params = {0};
+	const struct option opt = TEST_CALLBACK(&params, opt_aa_only_cb);
+
+	ck_assert_int_eq(opt_aa_only_cb(&opt, "10", 0), 0);
+	ck_assert_int_eq(opt_aa_only_cb(&opt, NULL, 1), 0);
+	ck_assert_int_eq(params.common.stop_us, 0);
+	ck_assert_int_eq(params.common.stop_total_us, 0);
+	ck_assert_int_eq(params.print_stack, 0);
+	ck_assert_int_eq(params.common.aa_only, 0);
+}
+END_TEST
+
 START_TEST(test_opt_timerlat_trace_output_cb)
 {
 	const char *trace_output = NULL;
@@ -480,6 +673,17 @@ START_TEST(test_opt_timerlat_trace_output_cb_noarg)
 }
 END_TEST
 
+START_TEST(test_opt_timerlat_trace_output_cb_unset)
+{
+	const char *trace_output = NULL;
+	const struct option opt = TEST_CALLBACK(&trace_output, opt_timerlat_trace_output_cb);
+
+	ck_assert_int_eq(opt_timerlat_trace_output_cb(&opt, "trace.txt", 0), 0);
+	ck_assert_int_eq(opt_timerlat_trace_output_cb(&opt, NULL, 1), 0);
+	ck_assert_ptr_null(trace_output);
+}
+END_TEST
+
 START_TEST(test_opt_timerlat_on_threshold_cb)
 {
 	struct actions actions = {0};
@@ -535,6 +739,18 @@ START_TEST(test_opt_user_threads_cb)
 }
 END_TEST
 
+START_TEST(test_opt_user_threads_cb_unset)
+{
+	struct timerlat_params params = {0};
+	const struct option opt = TEST_CALLBACK(&params, opt_user_threads_cb);
+
+	ck_assert_int_eq(opt_user_threads_cb(&opt, NULL, 0), 0);
+	ck_assert_int_eq(opt_user_threads_cb(&opt, NULL, 1), 0);
+	ck_assert_int_eq(params.common.user_workload, 0);
+	ck_assert_int_eq(params.common.user_data, 0);
+}
+END_TEST
+
 START_TEST(test_opt_nano_cb)
 {
 	struct timerlat_params params = {0};
@@ -545,6 +761,17 @@ START_TEST(test_opt_nano_cb)
 }
 END_TEST
 
+START_TEST(test_opt_nano_cb_unset)
+{
+	struct timerlat_params params = {0};
+	const struct option opt = TEST_CALLBACK(&params, opt_nano_cb);
+
+	ck_assert_int_eq(opt_nano_cb(&opt, NULL, 0), 0);
+	ck_assert_int_eq(opt_nano_cb(&opt, NULL, 1), 0);
+	ck_assert_int_eq(params.common.output_divisor, default_output_divisor);
+}
+END_TEST
+
 START_TEST(test_opt_timerlat_align_cb)
 {
 	struct timerlat_params params = {0};
@@ -556,6 +783,18 @@ START_TEST(test_opt_timerlat_align_cb)
 }
 END_TEST
 
+START_TEST(test_opt_timerlat_align_cb_unset)
+{
+	struct timerlat_params params = {0};
+	const struct option opt = TEST_CALLBACK(&params, opt_timerlat_align_cb);
+
+	ck_assert_int_eq(opt_timerlat_align_cb(&opt, "500", 0), 0);
+	ck_assert_int_eq(opt_timerlat_align_cb(&opt, NULL, 1), 0);
+	ck_assert_int_eq(params.timerlat_align, 0);
+	ck_assert_int_eq(params.timerlat_align_us, 0);
+}
+END_TEST
+
 START_TEST(test_opt_stack_format_cb)
 {
 	int stack_format = 0;
@@ -576,6 +815,17 @@ START_TEST(test_opt_stack_format_cb_invalid)
 }
 END_TEST
 
+START_TEST(test_opt_stack_format_cb_unset)
+{
+	int stack_format = 0;
+	const struct option opt = TEST_CALLBACK(&stack_format, opt_stack_format_cb);
+
+	ck_assert_int_eq(opt_stack_format_cb(&opt, "full", 0), 0);
+	ck_assert_int_eq(opt_stack_format_cb(&opt, NULL, 1), 0);
+	ck_assert_int_eq(stack_format, default_stack_format);
+}
+END_TEST
+
 START_TEST(test_opt_bucket_size_cb)
 {
 	int bucket_size = 0;
@@ -606,6 +856,17 @@ START_TEST(test_opt_bucket_size_max)
 }
 END_TEST
 
+START_TEST(test_opt_bucket_size_cb_unset)
+{
+	int bucket_size = 0;
+	const struct option opt = TEST_CALLBACK(&bucket_size, opt_bucket_size_cb);
+
+	ck_assert_int_eq(opt_bucket_size_cb(&opt, "100", 0), 0);
+	ck_assert_int_eq(opt_bucket_size_cb(&opt, NULL, 1), 0);
+	ck_assert_int_eq(bucket_size, default_bucket_size);
+}
+END_TEST
+
 START_TEST(test_opt_entries_cb)
 {
 	int entries = 0;
@@ -636,6 +897,17 @@ START_TEST(test_opt_entries_max)
 }
 END_TEST
 
+START_TEST(test_opt_entries_cb_unset)
+{
+	int entries = 0;
+	const struct option opt = TEST_CALLBACK(&entries, opt_entries_cb);
+
+	ck_assert_int_eq(opt_entries_cb(&opt, "100", 0), 0);
+	ck_assert_int_eq(opt_entries_cb(&opt, NULL, 1), 0);
+	ck_assert_int_eq(entries, default_entries);
+}
+END_TEST
+
 Suite *cli_opt_callback_suite(void)
 {
 	Suite *s = suite_create("cli_opt_callback");
@@ -645,23 +917,31 @@ Suite *cli_opt_callback_suite(void)
 	tcase_add_test(tc, test_opt_llong_callback_simple);
 	tcase_add_test(tc, test_opt_llong_callback_max);
 	tcase_add_test(tc, test_opt_llong_callback_min);
+	tcase_add_test(tc, test_opt_llong_callback_unset);
+	tcase_add_test(tc, test_opt_llong_callback_unset_defval);
 	tcase_add_test(tc, test_opt_int_callback_simple);
 	tcase_add_test(tc, test_opt_int_callback_max);
 	tcase_add_test(tc, test_opt_int_callback_min);
 	tcase_add_test(tc, test_opt_int_callback_non_numeric);
 	tcase_add_test(tc, test_opt_int_callback_non_numeric_suffix);
+	tcase_add_test(tc, test_opt_int_callback_unset);
+	tcase_add_test(tc, test_opt_int_callback_unset_defval);
 	tcase_add_test(tc, test_opt_cpus_cb);
 	tcase_add_exit_test(tc, test_opt_cpus_cb_invalid, EXIT_FAILURE);
 	tcase_add_test(tc, test_opt_cgroup_cb);
 	tcase_add_test(tc, test_opt_cgroup_cb_equals);
+	tcase_add_test(tc, test_opt_cgroup_cb_unset);
 	tcase_add_test(tc, test_opt_duration_cb);
+	tcase_add_test(tc, test_opt_duration_cb_unset);
 	tcase_add_exit_test(tc, test_opt_duration_cb_invalid, EXIT_FAILURE);
 	tcase_add_test(tc, test_opt_event_cb);
 	tcase_add_test(tc, test_opt_event_cb_multiple);
 	tcase_add_test(tc, test_opt_housekeeping_cb);
 	tcase_add_exit_test(tc, test_opt_housekeeping_cb_invalid, EXIT_FAILURE);
+	tcase_add_test(tc, test_opt_housekeeping_cb_unset);
 	tcase_add_test(tc, test_opt_priority_cb);
 	tcase_add_exit_test(tc, test_opt_priority_cb_invalid, EXIT_FAILURE);
+	tcase_add_test(tc, test_opt_priority_cb_unset);
 	tcase_add_test(tc, test_opt_trigger_cb);
 	tcase_add_exit_test(tc, test_opt_trigger_cb_no_event, EXIT_FAILURE);
 	tcase_add_test(tc, test_opt_filter_cb);
@@ -670,12 +950,16 @@ Suite *cli_opt_callback_suite(void)
 
 	tc = tcase_create("osnoise");
 	tcase_add_test(tc, test_opt_osnoise_auto_cb);
+	tcase_add_test(tc, test_opt_osnoise_auto_cb_unset);
 	tcase_add_test(tc, test_opt_osnoise_period_cb);
+	tcase_add_test(tc, test_opt_osnoise_period_cb_unset);
 	tcase_add_exit_test(tc, test_opt_osnoise_period_cb_invalid, EXIT_FAILURE);
 	tcase_add_test(tc, test_opt_osnoise_runtime_cb);
 	tcase_add_exit_test(tc, test_opt_osnoise_runtime_cb_invalid, EXIT_FAILURE);
+	tcase_add_test(tc, test_opt_osnoise_runtime_cb_unset);
 	tcase_add_test(tc, test_opt_osnoise_trace_output_cb);
 	tcase_add_test(tc, test_opt_osnoise_trace_output_cb_noarg);
+	tcase_add_test(tc, test_opt_osnoise_trace_output_cb_unset);
 	tcase_add_test(tc, test_opt_osnoise_on_threshold_cb);
 	tcase_add_exit_test(tc, test_opt_osnoise_on_threshold_cb_invalid, EXIT_FAILURE);
 	tcase_add_test(tc, test_opt_osnoise_on_end_cb);
@@ -685,31 +969,42 @@ Suite *cli_opt_callback_suite(void)
 	tc = tcase_create("timerlat");
 	tcase_add_test(tc, test_opt_timerlat_period_cb);
 	tcase_add_exit_test(tc, test_opt_timerlat_period_cb_invalid, EXIT_FAILURE);
+	tcase_add_test(tc, test_opt_timerlat_period_cb_unset);
 	tcase_add_test(tc, test_opt_timerlat_auto_cb);
+	tcase_add_test(tc, test_opt_timerlat_auto_cb_unset);
 	tcase_add_test(tc, test_opt_dma_latency_cb);
 	tcase_add_exit_test(tc, test_opt_dma_latency_cb_min, EXIT_FAILURE);
 	tcase_add_exit_test(tc, test_opt_dma_latency_cb_max, EXIT_FAILURE);
+	tcase_add_test(tc, test_opt_dma_latency_cb_unset);
 	tcase_add_test(tc, test_opt_aa_only_cb);
+	tcase_add_test(tc, test_opt_aa_only_cb_unset);
 	tcase_add_test(tc, test_opt_timerlat_trace_output_cb);
 	tcase_add_test(tc, test_opt_timerlat_trace_output_cb_noarg);
+	tcase_add_test(tc, test_opt_timerlat_trace_output_cb_unset);
 	tcase_add_test(tc, test_opt_timerlat_on_threshold_cb);
 	tcase_add_exit_test(tc, test_opt_timerlat_on_threshold_cb_invalid, EXIT_FAILURE);
 	tcase_add_test(tc, test_opt_timerlat_on_end_cb);
 	tcase_add_exit_test(tc, test_opt_timerlat_on_end_cb_invalid, EXIT_FAILURE);
 	tcase_add_test(tc, test_opt_user_threads_cb);
+	tcase_add_test(tc, test_opt_user_threads_cb_unset);
 	tcase_add_test(tc, test_opt_nano_cb);
+	tcase_add_test(tc, test_opt_nano_cb_unset);
 	tcase_add_test(tc, test_opt_stack_format_cb);
 	tcase_add_exit_test(tc, test_opt_stack_format_cb_invalid, EXIT_FAILURE);
+	tcase_add_test(tc, test_opt_stack_format_cb_unset);
 	tcase_add_test(tc, test_opt_timerlat_align_cb);
+	tcase_add_test(tc, test_opt_timerlat_align_cb_unset);
 	suite_add_tcase(s, tc);
 
 	tc = tcase_create("histogram");
 	tcase_add_test(tc, test_opt_bucket_size_cb);
 	tcase_add_exit_test(tc, test_opt_bucket_size_min, EXIT_FAILURE);
 	tcase_add_exit_test(tc, test_opt_bucket_size_max, EXIT_FAILURE);
+	tcase_add_test(tc, test_opt_bucket_size_cb_unset);
 	tcase_add_test(tc, test_opt_entries_cb);
 	tcase_add_exit_test(tc, test_opt_entries_min, EXIT_FAILURE);
 	tcase_add_exit_test(tc, test_opt_entries_max, EXIT_FAILURE);
+	tcase_add_test(tc, test_opt_entries_cb_unset);
 	suite_add_tcase(s, tc);
 
 	return s;
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 3/4] rtla: Add unit tests for CLI with unset
  2026-06-29  8:36 [PATCH 1/4] rtla: Allow unsetting non-list custom-callback CLI options Tomas Glozar
  2026-06-29  8:36 ` [PATCH 2/4] rtla: Add unit tests for unset in opt callbacks Tomas Glozar
@ 2026-06-29  8:36 ` Tomas Glozar
  2026-06-29  8:36 ` [PATCH 4/4] Documentation/rtla: Document unsetting options Tomas Glozar
  2 siblings, 0 replies; 4+ messages in thread
From: Tomas Glozar @ 2026-06-29  8:36 UTC (permalink / raw)
  To: Steven Rostedt, Tomas Glozar
  Cc: John Kacur, Luis Goncalves, Crystal Wood, Costa Shulyupin,
	Wander Lairson Costa, LKML, linux-trace-kernel

Test parsing of command line that sets an option and then unsets it back
to the default value in all tools.

Only two CLI tests are added for each tool: short period option (-p ...
--no-period) and long period option (--period ... --no-period). The
logic specific for individual options is tested in opt callback tests
already.

Signed-off-by: Tomas Glozar <tglozar@redhat.com>
---
 .../tracing/rtla/tests/unit/osnoise_hist_cli.c | 18 ++++++++++++++++++
 .../tracing/rtla/tests/unit/osnoise_top_cli.c  | 18 ++++++++++++++++++
 .../rtla/tests/unit/timerlat_hist_cli.c        | 18 ++++++++++++++++++
 .../tracing/rtla/tests/unit/timerlat_top_cli.c | 18 ++++++++++++++++++
 4 files changed, 72 insertions(+)

diff --git a/tools/tracing/rtla/tests/unit/osnoise_hist_cli.c b/tools/tracing/rtla/tests/unit/osnoise_hist_cli.c
index 3661529f93dc9..221985e6759f0 100644
--- a/tools/tracing/rtla/tests/unit/osnoise_hist_cli.c
+++ b/tools/tracing/rtla/tests/unit/osnoise_hist_cli.c
@@ -37,6 +37,22 @@ START_TEST(test_period_long)
 }
 END_TEST
 
+START_TEST(test_period_unset_short)
+{
+	PARSE_ARGS("osnoise", "hist", "-p", "100000", "--no-period");
+
+	ck_assert_int_eq(osn_params->period, 0);
+}
+END_TEST
+
+START_TEST(test_period_unset_long)
+{
+	PARSE_ARGS("osnoise", "hist", "--period", "100000", "--no-period");
+
+	ck_assert_int_eq(osn_params->period, 0);
+}
+END_TEST
+
 START_TEST(test_runtime_short)
 {
 	PARSE_ARGS("osnoise", "hist", "-r", "95000");
@@ -481,6 +497,8 @@ Suite *osnoise_hist_cli_suite(void)
 	tc = tcase_create("tracing_options");
 	tcase_add_test(tc, test_period_short);
 	tcase_add_test(tc, test_period_long);
+	tcase_add_test(tc, test_period_unset_short);
+	tcase_add_test(tc, test_period_unset_long);
 	tcase_add_test(tc, test_runtime_short);
 	tcase_add_test(tc, test_runtime_long);
 	tcase_add_test(tc, test_stop_short);
diff --git a/tools/tracing/rtla/tests/unit/osnoise_top_cli.c b/tools/tracing/rtla/tests/unit/osnoise_top_cli.c
index f3a8633cc84e8..057dbe574b079 100644
--- a/tools/tracing/rtla/tests/unit/osnoise_top_cli.c
+++ b/tools/tracing/rtla/tests/unit/osnoise_top_cli.c
@@ -37,6 +37,22 @@ START_TEST(test_period_long)
 }
 END_TEST
 
+START_TEST(test_period_unset_short)
+{
+	PARSE_ARGS("osnoise", "top", "-p", "100000", "--no-period");
+
+	ck_assert_int_eq(osn_params->period, 0);
+}
+END_TEST
+
+START_TEST(test_period_unset_long)
+{
+	PARSE_ARGS("osnoise", "top", "--period", "100000", "--no-period");
+
+	ck_assert_int_eq(osn_params->period, 0);
+}
+END_TEST
+
 START_TEST(test_runtime_short)
 {
 	PARSE_ARGS("osnoise", "top", "-r", "95000");
@@ -433,6 +449,8 @@ Suite *osnoise_top_cli_suite(void)
 	tc = tcase_create("tracing_options");
 	tcase_add_test(tc, test_period_short);
 	tcase_add_test(tc, test_period_long);
+	tcase_add_test(tc, test_period_unset_short);
+	tcase_add_test(tc, test_period_unset_long);
 	tcase_add_test(tc, test_runtime_short);
 	tcase_add_test(tc, test_runtime_long);
 	tcase_add_test(tc, test_stop_short);
diff --git a/tools/tracing/rtla/tests/unit/timerlat_hist_cli.c b/tools/tracing/rtla/tests/unit/timerlat_hist_cli.c
index 968bf962f53f0..d8dd9d752636e 100644
--- a/tools/tracing/rtla/tests/unit/timerlat_hist_cli.c
+++ b/tools/tracing/rtla/tests/unit/timerlat_hist_cli.c
@@ -55,6 +55,22 @@ START_TEST(test_period_long)
 }
 END_TEST
 
+START_TEST(test_period_unset_short)
+{
+	PARSE_ARGS("timerlat", "hist", "-p", "200", "--no-period");
+
+	ck_assert_int_eq(tlat_params->timerlat_period_us, 0);
+}
+END_TEST
+
+START_TEST(test_period_unset_long)
+{
+	PARSE_ARGS("timerlat", "hist", "--period", "200", "--no-period");
+
+	ck_assert_int_eq(tlat_params->timerlat_period_us, 0);
+}
+END_TEST
+
 START_TEST(test_stack_short)
 {
 	PARSE_ARGS("timerlat", "hist", "-s", "20");
@@ -629,6 +645,8 @@ Suite *timerlat_hist_cli_suite(void)
 	tcase_add_test(tc, test_irq_long);
 	tcase_add_test(tc, test_period_short);
 	tcase_add_test(tc, test_period_long);
+	tcase_add_test(tc, test_period_unset_short);
+	tcase_add_test(tc, test_period_unset_long);
 	tcase_add_test(tc, test_stack_short);
 	tcase_add_test(tc, test_stack_long);
 	tcase_add_test(tc, test_thread_short);
diff --git a/tools/tracing/rtla/tests/unit/timerlat_top_cli.c b/tools/tracing/rtla/tests/unit/timerlat_top_cli.c
index 33aa6588d503b..e9fb1a86ab8c4 100644
--- a/tools/tracing/rtla/tests/unit/timerlat_top_cli.c
+++ b/tools/tracing/rtla/tests/unit/timerlat_top_cli.c
@@ -55,6 +55,22 @@ START_TEST(test_period_long)
 }
 END_TEST
 
+START_TEST(test_period_unset_short)
+{
+	PARSE_ARGS("timerlat", "top", "-p", "200", "--no-period");
+
+	ck_assert_int_eq(tlat_params->timerlat_period_us, 0);
+}
+END_TEST
+
+START_TEST(test_period_unset_long)
+{
+	PARSE_ARGS("timerlat", "top", "--period", "200", "--no-period");
+
+	ck_assert_int_eq(tlat_params->timerlat_period_us, 0);
+}
+END_TEST
+
 START_TEST(test_stack_short)
 {
 	PARSE_ARGS("timerlat", "top", "-s", "20");
@@ -571,6 +587,8 @@ Suite *timerlat_top_cli_suite(void)
 	tcase_add_test(tc, test_irq_long);
 	tcase_add_test(tc, test_period_short);
 	tcase_add_test(tc, test_period_long);
+	tcase_add_test(tc, test_period_unset_short);
+	tcase_add_test(tc, test_period_unset_long);
 	tcase_add_test(tc, test_stack_short);
 	tcase_add_test(tc, test_stack_long);
 	tcase_add_test(tc, test_thread_short);
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 4/4] Documentation/rtla: Document unsetting options
  2026-06-29  8:36 [PATCH 1/4] rtla: Allow unsetting non-list custom-callback CLI options Tomas Glozar
  2026-06-29  8:36 ` [PATCH 2/4] rtla: Add unit tests for unset in opt callbacks Tomas Glozar
  2026-06-29  8:36 ` [PATCH 3/4] rtla: Add unit tests for CLI with unset Tomas Glozar
@ 2026-06-29  8:36 ` Tomas Glozar
  2 siblings, 0 replies; 4+ messages in thread
From: Tomas Glozar @ 2026-06-29  8:36 UTC (permalink / raw)
  To: Steven Rostedt, Tomas Glozar
  Cc: John Kacur, Luis Goncalves, Crystal Wood, Costa Shulyupin,
	Wander Lairson Costa, LKML, linux-trace-kernel

Add an appendix documenting how to unset options in RTLA. For options
where unsetting is currently not supported, add a note into the
respective section.

An additional note is added for --on-threshold trace. As it is
considered distinct from --trace, it is not reverted by --no-trace.

Signed-off-by: Tomas Glozar <tglozar@redhat.com>
---
 Documentation/tools/rtla/common_appendix.txt    | 17 +++++++++++++++++
 Documentation/tools/rtla/common_options.txt     | 13 ++++++++++++-
 .../tools/rtla/common_osnoise_options.txt       |  4 ++++
 .../tools/rtla/common_timerlat_options.txt      |  4 ++++
 4 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/Documentation/tools/rtla/common_appendix.txt b/Documentation/tools/rtla/common_appendix.txt
index 68cb15840d3a9..ad610ed02a240 100644
--- a/Documentation/tools/rtla/common_appendix.txt
+++ b/Documentation/tools/rtla/common_appendix.txt
@@ -1,5 +1,22 @@
 .. SPDX-License-Identifier: GPL-2.0
 
+UNSETTING OPTIONS
+=================
+
+The effect of most command line options can be reverted by prepending "no-" to
+the long variant of the option, for example:
+
+$ rtla timerlat top -p 100 --no-period
+
+resets the period back to the default value of 1000 us.
+
+If a command line option sets multiple RTLA parameters at once, the inverted
+option will revert all of them, even if they were not set by the particular
+option. For example, since using "--auto" implies "--trace", specifying
+"--trace --no-auto" will also disable trace output, just like if "--no-trace"
+was specified.
+
+
 SIGINT BEHAVIOR
 ===============
 
diff --git a/Documentation/tools/rtla/common_options.txt b/Documentation/tools/rtla/common_options.txt
index 6caa51d029347..38da1cf443a48 100644
--- a/Documentation/tools/rtla/common_options.txt
+++ b/Documentation/tools/rtla/common_options.txt
@@ -22,10 +22,14 @@
 
         Enable an event in the trace (**-t**) session. The argument can be a specific event, e.g., **-e** *sched:sched_switch*, or all events of a system group, e.g., **-e** *sched*. Multiple **-e** are allowed. It is only active when **-t** or **-a** are set.
 
+        This option cannot be unset.
+
 **--filter** *<filter>*
 
         Filter the previous **-e** *sys:event* event with *<filter>*. For further information about event filtering see https://www.kernel.org/doc/html/latest/trace/events.html#event-filtering.
 
+        This option cannot be unset.
+
 **--trigger** *<trigger>*
         Enable a trace event trigger to the previous **-e** *sys:event*.
         If the *hist:* trigger is activated, the output histogram will be automatically saved to a file named *system_event_hist.txt*.
@@ -37,6 +41,8 @@
 
         For further information about event trigger see https://www.kernel.org/doc/html/latest/trace/events.html#event-triggers.
 
+        This option cannot be unset.
+
 **-P**, **--priority** *o:prio|r:prio|f:prio|d:runtime:period*
 
         Set scheduling parameters to the |tool| tracer threads, the format to set the priority are:
@@ -78,7 +84,8 @@
 
           Saves trace output, optionally taking a filename. Alternative to -t/--trace.
           Note that unlike -t/--trace, specifying this multiple times will result in
-          the trace being saved multiple times.
+          the trace being saved multiple times, and --no-trace will not disable trace
+          output when enabled through this option.
 
         - *signal,num=<sig>,pid=<pid>*
 
@@ -107,6 +114,8 @@
 
         |actionsperf|
 
+        This option cannot be unset.
+
 **--on-end** *action*
 
         Defines an action to be executed at the end of tracing.
@@ -124,6 +133,8 @@
 
         This runs rtla with the default options, and saves trace output at the end.
 
+        This option cannot be unset.
+
 **-h**, **--help**
 
         Print help menu.
diff --git a/Documentation/tools/rtla/common_osnoise_options.txt b/Documentation/tools/rtla/common_osnoise_options.txt
index bd3c4f4991939..5fc70c0016158 100644
--- a/Documentation/tools/rtla/common_osnoise_options.txt
+++ b/Documentation/tools/rtla/common_osnoise_options.txt
@@ -24,11 +24,15 @@
         Stop the trace if a single sample is higher than the argument in microseconds.
         If **-T** is set, it will also save the trace to the output.
 
+        This option cannot be unset.
+
 **-S**, **--stop-total** *us*
 
         Stop the trace if the total sample is higher than the argument in microseconds.
         If **-T** is set, it will also save the trace to the output.
 
+        This option cannot be unset.
+
 **-T**, **--threshold** *us*
 
         Specify the minimum delta between two time reads to be considered noise.
diff --git a/Documentation/tools/rtla/common_timerlat_options.txt b/Documentation/tools/rtla/common_timerlat_options.txt
index 100840f4c0ed0..e36898438a0b0 100644
--- a/Documentation/tools/rtla/common_timerlat_options.txt
+++ b/Documentation/tools/rtla/common_timerlat_options.txt
@@ -23,10 +23,14 @@
 
         Stop trace if the *IRQ* latency is higher than the argument in us.
 
+        This option cannot be unset.
+
 **-T**, **--thread** *us*
 
         Stop trace if the *Thread* latency is higher than the argument in us.
 
+        This option cannot be unset.
+
 **-s**, **--stack** *us*
 
         Save the stack trace at the *IRQ* if a *Thread* latency is higher than the
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-06-29  8:37 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-29  8:36 [PATCH 1/4] rtla: Allow unsetting non-list custom-callback CLI options Tomas Glozar
2026-06-29  8:36 ` [PATCH 2/4] rtla: Add unit tests for unset in opt callbacks Tomas Glozar
2026-06-29  8:36 ` [PATCH 3/4] rtla: Add unit tests for CLI with unset Tomas Glozar
2026-06-29  8:36 ` [PATCH 4/4] Documentation/rtla: Document unsetting options Tomas Glozar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox