Linux Trace Kernel
 help / color / mirror / Atom feed
* Re: [PATCH] tracing: Add boot-time backup of persistent ring buffer
From: Steven Rostedt @ 2025-11-21 18:48 UTC (permalink / raw)
  To: Masami Hiramatsu (Google)
  Cc: Mathieu Desnoyers, linux-kernel, linux-trace-kernel
In-Reply-To: <176370846529.314463.7508792463190591259.stgit@mhiramat.tok.corp.google.com>

On Fri, 21 Nov 2025 16:01:05 +0900
"Masami Hiramatsu (Google)" <mhiramat@kernel.org> wrote:

> Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
> ---
>  kernel/trace/trace.c |   58 +++++++++++++++++++++++++++++++++++++++++++++++---
>  kernel/trace/trace.h |    1 +
>  2 files changed, 55 insertions(+), 4 deletions(-)
> 
> diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
> index 33fcde91924c..616d24580371 100644
> --- a/kernel/trace/trace.c
> +++ b/kernel/trace/trace.c
> @@ -10523,6 +10523,8 @@ static int __remove_instance(struct trace_array *tr)
>  		reserve_mem_release_by_name(tr->range_name);
>  		kfree(tr->range_name);
>  	}
> +	if (tr->flags & TRACE_ARRAY_FL_VMALLOC)
> +		vfree((void *)tr->range_addr_start);

The ring buffer user space mapping expects the ring buffer to be real
memory. Thus, virtual mapping is not supported. Either we need to allocate
normal memory, or the mmap function of his array must return an error.

>  
>  	for (i = 0; i < tr->nr_topts; i++) {
>  		kfree(tr->topts[i].topts);
> @@ -11328,6 +11330,41 @@ __init static void do_allocate_snapshot(const char *name)
>  static inline void do_allocate_snapshot(const char *name) { }
>  #endif
>  
> +__init static int backup_instance_area(const char *backup,
> +				       unsigned long *addr, phys_addr_t *size)
> +{
> +	struct trace_array *backup_tr;
> +	void *allocated_vaddr = NULL;
> +
> +	backup_tr = trace_array_get_by_name(backup, NULL);
> +	if (!backup_tr) {
> +		pr_warn("Tracing: Instance %s is not found.\n", backup);
> +		return -ENOENT;
> +	}

Add space.

> +	if (!(backup_tr->flags & TRACE_ARRAY_FL_BOOT)) {
> +		pr_warn("Tracing: Instance %s is not boot mapped.\n", backup);
> +		trace_array_put(backup_tr);
> +		return -EINVAL;
> +	}
> +
> +	*size = backup_tr->range_addr_size;
> +
> +	allocated_vaddr = vzalloc(*size);
> +	if (!allocated_vaddr) {
> +		pr_warn("Tracing: Failed to allocate memory for copying instance %s (size 0x%lx)\n",
> +			backup, (unsigned long)*size);
> +		trace_array_put(backup_tr);
> +		return -ENOMEM;
> +	}
> +
> +	memcpy(allocated_vaddr,
> +		(void *)backup_tr->range_addr_start, (size_t)*size);
> +	*addr = (unsigned long)allocated_vaddr;
> +
> +	trace_array_put(backup_tr);
> +	return 0;
> +}
> +
>  __init static void enable_instances(void)
>  {
>  	struct trace_array *tr;
> @@ -11350,11 +11387,15 @@ __init static void enable_instances(void)
>  		char *flag_delim;
>  		char *addr_delim;
>  		char *rname __free(kfree) = NULL;
> +		char *backup;
>  
>  		tok = strsep(&curr_str, ",");
>  
> -		flag_delim = strchr(tok, '^');
> -		addr_delim = strchr(tok, '@');
> +		name = strsep(&tok, "=");
> +		backup = tok;
> +
> +		flag_delim = strchr(name, '^');
> +		addr_delim = strchr(name, '@');
>  
>  		if (addr_delim)
>  			*addr_delim++ = '\0';
> @@ -11362,7 +11403,10 @@ __init static void enable_instances(void)
>  		if (flag_delim)
>  			*flag_delim++ = '\0';
>  
> -		name = tok;
> +		if (backup) {
> +			if (backup_instance_area(backup, &addr, &size) < 0)
> +				continue;
> +		}
>  
>  		if (flag_delim) {
>  			char *flag;
> @@ -11458,7 +11502,13 @@ __init static void enable_instances(void)
>  			tr->ref++;
>  		}
>  
> -		if (start) {
> +		/*
> +		 * Backup buffers can be freed but need vfree().
> +		 */
> +		if (backup)
> +			tr->flags |= TRACE_ARRAY_FL_VMALLOC;
> +
> +		if (start || backup) {
>  			tr->flags |= TRACE_ARRAY_FL_BOOT | TRACE_ARRAY_FL_LAST_BOOT;
>  			tr->range_name = no_free_ptr(rname);
>  		}

This would then need:

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index d1e527cf2aae..104e385e718e 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -8791,8 +8791,8 @@ static int tracing_buffers_mmap(struct file *filp, struct vm_area_struct *vma)
 	struct trace_iterator *iter = &info->iter;
 	int ret = 0;
 
-	/* A memmap'ed buffer is not supported for user space mmap */
-	if (iter->tr->flags & TRACE_ARRAY_FL_MEMMAP)
+	/* A memmap'ed and backup buffers are not supported for user space mmap */
+	if (iter->tr->flags & (TRACE_ARRAY_FL_MEMMAP | TRACE_ARRAY_FL_VMALLOC))
 		return -ENODEV;
 
 	ret = get_snapshot_map(iter->tr);


As without it, when I tried mmapping the backup buffer I got this;

[  251.615441] BUG: unable to handle page fault for address: ffffd1c31e0000c8
[  251.615447] #PF: supervisor read access in kernel mode
[  251.615449] #PF: error_code(0x0000) - not-present page
[  251.615451] PGD 0 P4D 0 
[  251.615456] Oops: Oops: 0000 [#1] SMP PTI
[  251.615463] CPU: 6 UID: 0 PID: 1450 Comm: mmap-rb-lib Not tainted 6.18.0-rc3-ftest-00018-g02548113c2f6 #287 PREEMPT_{RT,LAZY} 
[  251.615469] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.17.0-debian-1.17.0-1 04/01/2014
[  251.615471] RIP: 0010:validate_page_before_insert+0x5/0x90
[  251.615479] Code: 48 c1 e8 0e 89 c2 83 e2 01 89 d0 c3 cc cc cc cc 0f 1f 44 00 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 0f 1f 44 00 00 <48> 8b 46 08 a8 01 75 5d 66 90 48 89 f0 8b 50 34 85 d2 74 68 48 89
[  251.615481] RSP: 0018:ffffa52b443d7988 EFLAGS: 00010246
[  251.615484] RAX: ffff8a84dcac4000 RBX: 00007f07e0c10000 RCX: 0000000108d2f067
[  251.615486] RDX: 0000000108d2f067 RSI: ffffd1c31e0000c0 RDI: ffff8a84dd865700
[  251.615487] RBP: 0000000000000000 R08: 000000005ab70715 R09: 0000000000000009
[  251.615489] R10: 0000000000000009 R11: ffff8a84c9320fb8 R12: ffff8a84dd865700
[  251.615490] R13: 0000000000000000 R14: ffffd1c31e0000c0 R15: ffff8a84c8d2f080
[  251.615492] FS:  00007f07e0e8e740(0000) GS:ffff8a86afbb7000(0000) knlGS:0000000000000000
[  251.615494] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  251.615496] CR2: ffffd1c31e0000c8 CR3: 000000011c390006 CR4: 0000000000170ef0
[  251.615501] Call Trace:
[  251.615502]  <TASK>
[  251.615504]  vm_insert_pages+0x157/0x360
[  251.615513]  __rb_map_vma+0x1ef/0x390
[  251.615521]  ring_buffer_map+0x261/0x370
[  251.615527]  tracing_buffers_mmap+0x7e/0x100
[  251.615532]  __mmap_region+0x831/0xe00
[  251.615554]  do_mmap+0x4bf/0x6b0
[  251.615560]  vm_mmap_pgoff+0x126/0x230
[  251.615569]  ksys_mmap_pgoff+0x162/0x220
[  251.615573]  do_syscall_64+0x76/0x9a0
[  251.615581]  entry_SYSCALL_64_after_hwframe+0x76/0x7e
[  251.615584] RIP: 0033:0x7f07e0f9dde2
[  251.615589] Code: 00 00 00 0f 1f 44 00 00 

-- Steve


> diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
> index 58be6d741d72..9e5186c96e9c 100644
> --- a/kernel/trace/trace.h
> +++ b/kernel/trace/trace.h
> @@ -453,6 +453,7 @@ enum {
>  	TRACE_ARRAY_FL_LAST_BOOT	= BIT(2),
>  	TRACE_ARRAY_FL_MOD_INIT		= BIT(3),
>  	TRACE_ARRAY_FL_MEMMAP		= BIT(4),
> +	TRACE_ARRAY_FL_VMALLOC		= BIT(5),
>  };
>  
>  #ifdef CONFIG_MODULES


^ permalink raw reply related

* Re: [PATCH v9 1/2] lib: Introduce hierarchical per-cpu counters
From: Christoph Lameter (Ampere) @ 2025-11-21 18:30 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Mathieu Desnoyers, linux-kernel, Paul E. McKenney, Steven Rostedt,
	Masami Hiramatsu, Dennis Zhou, Tejun Heo, Martin Liu,
	David Rientjes, christian.koenig, Shakeel Butt, SeongJae Park,
	Michal Hocko, Johannes Weiner, Sweet Tea Dorminy, Lorenzo Stoakes,
	Liam R . Howlett, Mike Rapoport, Suren Baghdasaryan,
	Vlastimil Babka, Christian Brauner, Wei Yang, David Hildenbrand,
	Miaohe Lin, Al Viro, linux-mm, linux-trace-kernel, Yu Zhao,
	Roman Gushchin, Mateusz Guzik, Matthew Wilcox, Baolin Wang,
	Aboorva Devarajan
In-Reply-To: <20251121100308.65b36af9e090a78a66144c6c@linux-foundation.org>

On Fri, 21 Nov 2025, Andrew Morton wrote:

> Have you identified other parts of the kernel which could use this?

We need to compare this with the ZVC counters used for the vm statistics.
Maybe this is better and we can scale counters easier in the VM.

ZVCs were designed for systems with a large number of NUMA nodes and a
handful of processors in each of those. What we have today is large number
of processors in one socket (my employer is shooting high on that level).

Hierachical counters may be better in that scenario. Maybe we can call
them HVC (Hierachical VM Counters). ;-) )



^ permalink raw reply

* Re: [PATCH v9 1/2] lib: Introduce hierarchical per-cpu counters
From: Andrew Morton @ 2025-11-21 18:03 UTC (permalink / raw)
  To: Mathieu Desnoyers
  Cc: linux-kernel, Paul E. McKenney, Steven Rostedt, Masami Hiramatsu,
	Dennis Zhou, Tejun Heo, Christoph Lameter, Martin Liu,
	David Rientjes, christian.koenig, Shakeel Butt, SeongJae Park,
	Michal Hocko, Johannes Weiner, Sweet Tea Dorminy, Lorenzo Stoakes,
	Liam R . Howlett, Mike Rapoport, Suren Baghdasaryan,
	Vlastimil Babka, Christian Brauner, Wei Yang, David Hildenbrand,
	Miaohe Lin, Al Viro, linux-mm, linux-trace-kernel, Yu Zhao,
	Roman Gushchin, Mateusz Guzik, Matthew Wilcox, Baolin Wang,
	Aboorva Devarajan
In-Reply-To: <20251120210354.1233994-2-mathieu.desnoyers@efficios.com>

On Thu, 20 Nov 2025 16:03:53 -0500 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> wrote:

> * Motivation
> 
> The purpose of this hierarchical split-counter scheme is to:
> 
> - Minimize contention when incrementing and decrementing counters,
> - Provide fast access to a sum approximation,
> - Provide a sum approximation with an acceptable accuracy level when
>   scaling to many-core systems.
> - Provide approximate and precise comparison of two counters, and
>   between a counter and a value.
> 
> It aims at fixing the per-mm RSS tracking which has become too
> inaccurate for OOM killer purposes on large many-core systems [1].

Presentation nit: the info at [1] is rather well hidden until one reads
the [2/2] changelog.  You might want to move that material into the
[0/N] - after all, it's the entire point of the patchset.

> * Design
> 
> The hierarchical per-CPU counters propagate a sum approximation through
> a N-way tree. When reaching the batch size, the carry is propagated
> through a binary tree which consists of logN(nr_cpu_ids) levels. The
> batch size for each level is twice the batch size of the prior level.
> 
> Example propagation diagram with 8 cpus through a binary tree:
> 
> Level 0:  0    1    2    3    4    5    6    7
>           |   /     |   /     |   /     |   /
>           |  /      |  /      |  /      |  /
>           | /       | /       | /       | /
> Level 1:  0         1         2         3
>           |       /           |       /
>           |    /              |    /
>           | /                 | /
> Level 2:  0                   1
>           |               /
>           |         /
>           |   /
> Level 3:  0
> 
> For a binary tree, the maximum inaccuracy is bound by:
>    batch_size * log2(nr_cpus) * nr_cpus
> which evolves with O(n*log(n)) as the number of CPUs increases.
> 
> For a N-way tree, the maximum inaccuracy can be pre-calculated
> based on the the N-arity of each level and the batch size.

Looks very neat.

Have you identified other parts of the kernel which could use this?

>  include/linux/percpu_counter_tree.h | 239 +++++++++++++++
>  init/main.c                         |   2 +
>  lib/Makefile                        |   1 +
>  lib/percpu_counter_tree.c           | 443 ++++++++++++++++++++++++++++
>  4 files changed, 685 insertions(+)
>  create mode 100644 include/linux/percpu_counter_tree.h
>  create mode 100644 lib/percpu_counter_tree.c

An in-kernel test suite would be great.  Like lib/*test*.c or
tools/testing/.

> diff --git a/include/linux/percpu_counter_tree.h b/include/linux/percpu_counter_tree.h
> new file mode 100644
> index 000000000000..1f4938b67730
> --- /dev/null
> +++ b/include/linux/percpu_counter_tree.h
> @@ -0,0 +1,239 @@
> +/* SPDX-License-Identifier: GPL-2.0+ OR MIT */
> +/* SPDX-FileCopyrightText: 2025 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> */
> +
> +#ifndef _PERCPU_COUNTER_TREE_H
> +#define _PERCPU_COUNTER_TREE_H
> +
> +#include <linux/preempt.h>
> +#include <linux/atomic.h>
> +#include <linux/percpu.h>
> +
> +#ifdef CONFIG_SMP
> +
> +struct percpu_counter_tree_level_item {
> +	atomic_t count;
> +} ____cacheline_aligned_in_smp;
> +
> +struct percpu_counter_tree {
> +	/* Fast-path fields. */
> +	unsigned int __percpu *level0;
> +	unsigned int level0_bit_mask;
> +	union {
> +		unsigned int *i;
> +		atomic_t *a;
> +	} approx_sum;
> +	int bias;			/* bias for counter_set */
> +
> +	/* Slow-path fields. */
> +	struct percpu_counter_tree_level_item *items;
> +	unsigned int batch_size;
> +	unsigned int inaccuracy;	/* approximation imprecise within ± inaccuracy */
> +};

I find that understanding the data structure leads to understanding the
code, so additional documentation for the various fields would be
helpful.

> +
> +static inline
> +int percpu_counter_tree_carry(int orig, int res, int inc, unsigned int bit_mask)
> +{
> ...
> +}
> +
> +static inline
> +void percpu_counter_tree_add(struct percpu_counter_tree *counter, int inc)
> +{
> ...
> +}
> +
> +static inline
> +int percpu_counter_tree_approximate_sum(struct percpu_counter_tree *counter)
> +{
> ...
> +}

These are pretty large after all the nested inlining is expanded.  Are
you sure that inlining them is the correct call?


> +#else	/* !CONFIG_SMP */
> +
>
> ...
>
> +#include <linux/percpu_counter_tree.h>
> +#include <linux/cpumask.h>
> +#include <linux/percpu.h>
> +#include <linux/atomic.h>
> +#include <linux/errno.h>
> +#include <linux/slab.h>
> +#include <linux/math.h>
> +
> +#define MAX_NR_LEVELS 5
> +
> +struct counter_config {
> +	unsigned int nr_items;
> +	unsigned char nr_levels;
> +	unsigned char n_arity_order[MAX_NR_LEVELS];
> +};
> +
> +/*
> + * nr_items is the number of items in the tree for levels 1 to and
> + * including the final level (approximate sum). It excludes the level 0
> + * per-cpu counters.
> + */

That's referring to counter_config.nr_items?  Comment appears to be
misplaced.

>
> ...
>
> +static
> +int __percpu_counter_tree_init(struct percpu_counter_tree *counter,
> +			       unsigned int batch_size, gfp_t gfp_flags,
> +			       unsigned int __percpu *level0,
> +			       struct percpu_counter_tree_level_item *items)
> +{
> +	/* Batch size must be power of 2 */
> +	if (!batch_size || (batch_size & (batch_size - 1)))
> +		return -EINVAL;

It's a bug, yes?  Worth a WARN?

> +	counter->batch_size = batch_size;
> +	counter->bias = 0;
> +	counter->level0 = level0;
> +	counter->items = items;
> +	if (!nr_cpus_order) {
> +		counter->approx_sum.i = per_cpu_ptr(counter->level0, 0);
> +		counter->level0_bit_mask = 0;
> +	} else {
> +		counter->approx_sum.a = &counter->items[counter_config->nr_items - 1].count;
> +		counter->level0_bit_mask = 1UL << get_count_order(batch_size);
> +	}
> +	counter->inaccuracy = batch_size * inaccuracy_multiplier;
> +	return 0;
> +}
> +
>
> ...
>
> +int percpu_counter_tree_precise_sum(struct percpu_counter_tree *counter)
> +{
> +	return percpu_counter_tree_precise_sum_unbiased(counter) + READ_ONCE(counter->bias);
> +}
> +
> +/*
> + * Do an approximate comparison of two counters.
> + * Return 0 if counters do not differ by more than the sum of their
> + * respective inaccuracy ranges,
> + * Return -1 if counter @a less than counter @b,
> + * Return 1 if counter @a is greater than counter @b.
> + */

It would be nice to kerneldocify the exported API.

Some fairly detailed words explaining the pros and cons of precise vs
approximate would be helpful to people who are using this API.

> +int percpu_counter_tree_approximate_compare(struct percpu_counter_tree *a, struct percpu_counter_tree *b)
> +{
> +	int count_a = percpu_counter_tree_approximate_sum(a),
> +	    count_b = percpu_counter_tree_approximate_sum(b);
> +
> +	if (abs(count_a - count_b) <= (a->inaccuracy + b->inaccuracy))
> +		return 0;
> +	if (count_a < count_b)
> +		return -1;
> +	return 1;
> +}
> +
>
> ...
>
> +static unsigned int __init calculate_inaccuracy_multiplier(void)
> +{
> +	unsigned int nr_levels = counter_config->nr_levels, level;
> +	unsigned int level_items = 1U << nr_cpus_order;
> +	unsigned int inaccuracy = 0, batch_size = 1;
> +
> +	for (level = 0; level < nr_levels; level++) {
> +		unsigned int n_arity_order = counter_config->n_arity_order[level];
> +
> +		inaccuracy += batch_size * level_items;
> +		batch_size <<= n_arity_order;
> +		level_items >>= n_arity_order;
> +	}
> +	return inaccuracy;
> +}
> +
> +int __init percpu_counter_tree_subsystem_init(void)

I'm not sure that the "subsystem_" adds any value.

> +{
> +
> +	nr_cpus_order = get_count_order(nr_cpu_ids);

Stray newline.

> +	if (WARN_ON_ONCE(nr_cpus_order >= ARRAY_SIZE(per_nr_cpu_order_config))) {
> +		printk(KERN_ERR "Unsupported number of CPUs (%u)\n", nr_cpu_ids);
> +		return -1;
> +	}
> +	counter_config = &per_nr_cpu_order_config[nr_cpus_order];
> +	inaccuracy_multiplier = calculate_inaccuracy_multiplier();
> +	return 0;
> +}


^ permalink raw reply

* Re: [RFC PATCH v7 30/31] x86/mm, mm/vmalloc: Defer kernel TLB flush IPIs under CONFIG_COALESCE_TLBI=y
From: Dave Hansen @ 2025-11-21 17:50 UTC (permalink / raw)
  To: Valentin Schneider, linux-kernel, linux-mm, rcu, x86,
	linux-arm-kernel, loongarch, linux-riscv, linux-arch,
	linux-trace-kernel
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
	H. Peter Anvin, Andy Lutomirski, Peter Zijlstra,
	Arnaldo Carvalho de Melo, Josh Poimboeuf, Paolo Bonzini,
	Arnd Bergmann, Frederic Weisbecker, Paul E. McKenney, Jason Baron,
	Steven Rostedt, Ard Biesheuvel, Sami Tolvanen, David S. Miller,
	Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Boqun Feng,
	Uladzislau Rezki, Mathieu Desnoyers, Mel Gorman, Andrew Morton,
	Masahiro Yamada, Han Shen, Rik van Riel, Jann Horn, Dan Carpenter,
	Oleg Nesterov, Juri Lelli, Clark Williams, Yair Podemsky,
	Marcelo Tosatti, Daniel Wagner, Petr Tesarik, Shrikanth Hegde
In-Reply-To: <xhsmh5xb3thh6.mognet@vschneid-thinkpadt14sgen2i.remote.csb>

On 11/21/25 09:37, Valentin Schneider wrote:
> On 19/11/25 10:31, Dave Hansen wrote:
>> On 11/14/25 07:14, Valentin Schneider wrote:
>>> +static bool flush_tlb_kernel_cond(int cpu, void *info)
>>> +{
>>> +	return housekeeping_cpu(cpu, HK_TYPE_KERNEL_NOISE) ||
>>> +	       per_cpu(kernel_cr3_loaded, cpu);
>>> +}
>>
>> Is it OK that 'kernel_cr3_loaded' can be be stale? Since it's not part
>> of the instruction that actually sets CR3, there's a window between when
>> 'kernel_cr3_loaded' is set (or cleared) and CR3 is actually written.
>>
>> Is that OK?
>>
>> It seems like it could lead to both unnecessary IPIs being sent and for
>> IPIs to be missed.
>>
> 
> So the pattern is
> 
>   SWITCH_TO_KERNEL_CR3
>   FLUSH
>   KERNEL_CR3_LOADED := 1
> 
>   KERNEL_CR3_LOADED := 0
>   SWITCH_TO_USER_CR3
> 
> 
> The 0 -> 1 transition has a window between the unconditional flush and the
> write to 1 where a remote flush IPI may be omitted. Given that the write is
> immediately following the unconditional flush, that would really be just
> two flushes racing with each other,

Let me fix that for you. When you wrote "a remote flush IPI may be
omitted" you meant to write: "there's a bug." ;)

In the end, KERNEL_CR3_LOADED==0 means, "you don't need to send this CPU
flushing IPIs because it will flush the TLB itself before touching
memory that needs a flush".

   SWITCH_TO_KERNEL_CR3
   FLUSH
   // On kernel CR3, *AND* not getting IPIs
   KERNEL_CR3_LOADED := 1

> but I could punt the kernel_cr3_loaded
> write above the unconditional flush.

Yes, that would eliminate the window, as long as the memory ordering is
right. You not only need to have the KERNEL_CR3_LOADED:=1 CPU set that
variable, you need to ensure that it has seen the page table update.

> The 1 -> 0 transition is less problematic, worst case a remote flush races
> with the CPU returning to userspace and it'll get interrupted back to
> kernelspace.

It's also not just "returning to userspace". It could well be *in*
userspace by the point the IPI shows up. It's not the end of the world,
and the window isn't infinitely long. But there certainly is still a
possibility of getting spurious interrupts for the precious NOHZ_FULL
task while it's in userspace.

^ permalink raw reply

* [PATCH v1 8/8] tools/rtla: Consolidate -H/--house-keeping option parsing
From: Costa Shulyupin @ 2025-11-21 17:45 UTC (permalink / raw)
  To: Steven Rostedt, Tomas Glozar, Costa Shulyupin, Crystal Wood,
	Wander Lairson Costa, Ivan Pravdin, linux-trace-kernel,
	linux-kernel
In-Reply-To: <20251121174504.519230-1-costa.shul@redhat.com>

Each rtla tool duplicates parsing of -H/--house-keeping.

Migrate the option parsing from individual tools to the
common_parse_options().

Signed-off-by: Costa Shulyupin <costa.shul@redhat.com>
---
 tools/tracing/rtla/src/common.c        | 8 +++++++-
 tools/tracing/rtla/src/osnoise_hist.c  | 9 +--------
 tools/tracing/rtla/src/osnoise_top.c   | 9 +--------
 tools/tracing/rtla/src/timerlat_hist.c | 9 +--------
 tools/tracing/rtla/src/timerlat_top.c  | 9 +--------
 5 files changed, 11 insertions(+), 33 deletions(-)

diff --git a/tools/tracing/rtla/src/common.c b/tools/tracing/rtla/src/common.c
index dd67c6b47eaa..9d047a64146b 100644
--- a/tools/tracing/rtla/src/common.c
+++ b/tools/tracing/rtla/src/common.c
@@ -62,12 +62,13 @@ int common_parse_options(int argc, char **argv, struct common_params *common)
 		{"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_long(argc, argv, "c:C::Dd:e:P:", long_options, NULL);
+	c = getopt_long(argc, argv, "c:C::Dd:e:H:P:", long_options, NULL);
 
 	switch (c) {
 	case 'c':
@@ -96,6 +97,11 @@ int common_parse_options(int argc, char **argv, struct common_params *common)
 			tevent->next = common->events;
 		common->events = tevent;
 		break;
+	case 'H':
+		common->hk_cpus = 1;
+		if (parse_cpu_set(optarg, &common->hk_cpu_set))
+			fatal("Error parsing house keeping CPUs");
+		break;
 	case 'P':
 		if (parse_prio(optarg, &common->sched_param) == -1)
 			fatal("Invalid -P priority");
diff --git a/tools/tracing/rtla/src/osnoise_hist.c b/tools/tracing/rtla/src/osnoise_hist.c
index 6ed5f5594960..1ebd3b48b2d3 100644
--- a/tools/tracing/rtla/src/osnoise_hist.c
+++ b/tools/tracing/rtla/src/osnoise_hist.c
@@ -490,7 +490,6 @@ static struct common_params
 			{"auto",		required_argument,	0, 'a'},
 			{"bucket-size",		required_argument,	0, 'b'},
 			{"entries",		required_argument,	0, 'E'},
-			{"house-keeping",	required_argument,		0, 'H'},
 			{"help",		no_argument,		0, 'h'},
 			{"period",		required_argument,	0, 'p'},
 			{"runtime",		required_argument,	0, 'r'},
@@ -514,7 +513,7 @@ static struct common_params
 		if (common_parse_options(argc, argv, &params->common))
 			continue;
 
-		c = getopt_long(argc, argv, "a:b:E:hH:p:r:s:S:t::T:01234:5:6:7:",
+		c = getopt_long(argc, argv, "a:b:E:hp:r:s:S:t::T:01234:5:6:7:",
 				 long_options, NULL);
 
 		/* detect the end of the options. */
@@ -550,12 +549,6 @@ static struct common_params
 		case '?':
 			osnoise_hist_usage();
 			break;
-		case 'H':
-			params->common.hk_cpus = 1;
-			retval = parse_cpu_set(optarg, &params->common.hk_cpu_set);
-			if (retval)
-				fatal("Error parsing house keeping CPUs");
-			break;
 		case 'p':
 			params->period = get_llong_from_str(optarg);
 			if (params->period > 10000000)
diff --git a/tools/tracing/rtla/src/osnoise_top.c b/tools/tracing/rtla/src/osnoise_top.c
index d2dfad960440..02e5e6e18e8d 100644
--- a/tools/tracing/rtla/src/osnoise_top.c
+++ b/tools/tracing/rtla/src/osnoise_top.c
@@ -345,7 +345,6 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv)
 	while (1) {
 		static struct option long_options[] = {
 			{"auto",		required_argument,	0, 'a'},
-			{"house-keeping",	required_argument,	0, 'H'},
 			{"help",		no_argument,		0, 'h'},
 			{"period",		required_argument,	0, 'p'},
 			{"quiet",		no_argument,		0, 'q'},
@@ -366,7 +365,7 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv)
 		if (common_parse_options(argc, argv, &params->common))
 			continue;
 
-		c = getopt_long(argc, argv, "a:hH:p:qr:s:S:t::T:0:1:2:3:",
+		c = getopt_long(argc, argv, "a:hp:qr:s:S:t::T:0:1:2:3:",
 				 long_options, NULL);
 
 		/* Detect the end of the options. */
@@ -390,12 +389,6 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv)
 		case '?':
 			osnoise_top_usage(params);
 			break;
-		case 'H':
-			params->common.hk_cpus = 1;
-			retval = parse_cpu_set(optarg, &params->common.hk_cpu_set);
-			if (retval)
-				fatal("Error parsing house keeping CPUs");
-			break;
 		case 'p':
 			params->period = get_llong_from_str(optarg);
 			if (params->period > 10000000)
diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/src/timerlat_hist.c
index e7ba083b5eb4..d1a6cf0c2e0d 100644
--- a/tools/tracing/rtla/src/timerlat_hist.c
+++ b/tools/tracing/rtla/src/timerlat_hist.c
@@ -797,7 +797,6 @@ static struct common_params
 			{"auto",		required_argument,	0, 'a'},
 			{"bucket-size",		required_argument,	0, 'b'},
 			{"entries",		required_argument,	0, 'E'},
-			{"house-keeping",	required_argument,	0, 'H'},
 			{"help",		no_argument,		0, 'h'},
 			{"irq",			required_argument,	0, 'i'},
 			{"nano",		no_argument,		0, 'n'},
@@ -830,7 +829,7 @@ static struct common_params
 		if (common_parse_options(argc, argv, &params->common))
 			continue;
 
-		c = getopt_long(argc, argv, "a:b:E:hH:i:knp:s:t::T:uU0123456:7:8:9\1\2:\3:",
+		c = getopt_long(argc, argv, "a:b:E:hi:knp:s:t::T:uU0123456:7:8:9\1\2:\3:",
 				 long_options, NULL);
 
 		/* detect the end of the options. */
@@ -869,12 +868,6 @@ static struct common_params
 		case '?':
 			timerlat_hist_usage();
 			break;
-		case 'H':
-			params->common.hk_cpus = 1;
-			retval = parse_cpu_set(optarg, &params->common.hk_cpu_set);
-			if (retval)
-				fatal("Error parsing house keeping CPUs");
-			break;
 		case 'i':
 			params->common.stop_us = get_llong_from_str(optarg);
 			break;
diff --git a/tools/tracing/rtla/src/timerlat_top.c b/tools/tracing/rtla/src/timerlat_top.c
index 8250bea4b2fd..12e3d8c6f850 100644
--- a/tools/tracing/rtla/src/timerlat_top.c
+++ b/tools/tracing/rtla/src/timerlat_top.c
@@ -566,7 +566,6 @@ static struct common_params
 		static struct option long_options[] = {
 			{"auto",		required_argument,	0, 'a'},
 			{"help",		no_argument,		0, 'h'},
-			{"house-keeping",	required_argument,	0, 'H'},
 			{"irq",			required_argument,	0, 'i'},
 			{"nano",		no_argument,		0, 'n'},
 			{"period",		required_argument,	0, 'p'},
@@ -594,7 +593,7 @@ static struct common_params
 		if (common_parse_options(argc, argv, &params->common))
 			continue;
 
-		c = getopt_long(argc, argv, "a:hH:i:knp:qs:t::T:uU0:1:2:345:6:7:",
+		c = getopt_long(argc, argv, "a:hi:knp:qs:t::T:uU0:1:2:345:6:7:",
 				 long_options, NULL);
 
 		/* detect the end of the options. */
@@ -635,12 +634,6 @@ static struct common_params
 		case '?':
 			timerlat_top_usage();
 			break;
-		case 'H':
-			params->common.hk_cpus = 1;
-			retval = parse_cpu_set(optarg, &params->common.hk_cpu_set);
-			if (retval)
-				fatal("Error parsing house keeping CPUs");
-			break;
 		case 'i':
 			params->common.stop_us = get_llong_from_str(optarg);
 			break;
-- 
2.51.1


^ permalink raw reply related

* [PATCH v1 7/8] tools/rtla: Consolidate -P/--priority option parsing
From: Costa Shulyupin @ 2025-11-21 17:45 UTC (permalink / raw)
  To: Steven Rostedt, Tomas Glozar, Costa Shulyupin, Crystal Wood,
	Wander Lairson Costa, Ivan Pravdin, linux-trace-kernel,
	linux-kernel
In-Reply-To: <20251121174504.519230-1-costa.shul@redhat.com>

Each rtla tool duplicates parsing of -P/--priority.

Migrate the option parsing from individual tools to the
common_parse_options().

Signed-off-by: Costa Shulyupin <costa.shul@redhat.com>
---
 tools/tracing/rtla/src/common.c        | 8 +++++++-
 tools/tracing/rtla/src/osnoise_hist.c  | 9 +--------
 tools/tracing/rtla/src/osnoise_top.c   | 9 +--------
 tools/tracing/rtla/src/timerlat_hist.c | 9 +--------
 tools/tracing/rtla/src/timerlat_top.c  | 9 +--------
 5 files changed, 11 insertions(+), 33 deletions(-)

diff --git a/tools/tracing/rtla/src/common.c b/tools/tracing/rtla/src/common.c
index 6a1675eba96e..dd67c6b47eaa 100644
--- a/tools/tracing/rtla/src/common.c
+++ b/tools/tracing/rtla/src/common.c
@@ -62,11 +62,12 @@ int common_parse_options(int argc, char **argv, struct common_params *common)
 		{"debug",               no_argument,            0, 'D'},
 		{"duration",            required_argument,      0, 'd'},
 		{"event",               required_argument,      0, 'e'},
+		{"priority",            required_argument,      0, 'P'},
 		{0, 0, 0, 0}
 	};
 
 	opterr = 0;
-	c = getopt_long(argc, argv, "c:C::Dd:e:", long_options, NULL);
+	c = getopt_long(argc, argv, "c:C::Dd:e:P:", long_options, NULL);
 
 	switch (c) {
 	case 'c':
@@ -95,6 +96,11 @@ int common_parse_options(int argc, char **argv, struct common_params *common)
 			tevent->next = common->events;
 		common->events = tevent;
 		break;
+	case 'P':
+		if (parse_prio(optarg, &common->sched_param) == -1)
+			fatal("Invalid -P priority");
+		common->set_sched = 1;
+		break;
 	default:
 		optind = saved_state;
 		return 0;
diff --git a/tools/tracing/rtla/src/osnoise_hist.c b/tools/tracing/rtla/src/osnoise_hist.c
index c4013f50e803..6ed5f5594960 100644
--- a/tools/tracing/rtla/src/osnoise_hist.c
+++ b/tools/tracing/rtla/src/osnoise_hist.c
@@ -493,7 +493,6 @@ static struct common_params
 			{"house-keeping",	required_argument,		0, 'H'},
 			{"help",		no_argument,		0, 'h'},
 			{"period",		required_argument,	0, 'p'},
-			{"priority",		required_argument,	0, 'P'},
 			{"runtime",		required_argument,	0, 'r'},
 			{"stop",		required_argument,	0, 's'},
 			{"stop-total",		required_argument,	0, 'S'},
@@ -515,7 +514,7 @@ static struct common_params
 		if (common_parse_options(argc, argv, &params->common))
 			continue;
 
-		c = getopt_long(argc, argv, "a:b:E:hH:p:P:r:s:S:t::T:01234:5:6:7:",
+		c = getopt_long(argc, argv, "a:b:E:hH:p:r:s:S:t::T:01234:5:6:7:",
 				 long_options, NULL);
 
 		/* detect the end of the options. */
@@ -562,12 +561,6 @@ static struct common_params
 			if (params->period > 10000000)
 				fatal("Period longer than 10 s");
 			break;
-		case 'P':
-			retval = parse_prio(optarg, &params->common.sched_param);
-			if (retval == -1)
-				fatal("Invalid -P priority");
-			params->common.set_sched = 1;
-			break;
 		case 'r':
 			params->runtime = get_llong_from_str(optarg);
 			if (params->runtime < 100)
diff --git a/tools/tracing/rtla/src/osnoise_top.c b/tools/tracing/rtla/src/osnoise_top.c
index 846d25ee4885..d2dfad960440 100644
--- a/tools/tracing/rtla/src/osnoise_top.c
+++ b/tools/tracing/rtla/src/osnoise_top.c
@@ -348,7 +348,6 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv)
 			{"house-keeping",	required_argument,	0, 'H'},
 			{"help",		no_argument,		0, 'h'},
 			{"period",		required_argument,	0, 'p'},
-			{"priority",		required_argument,	0, 'P'},
 			{"quiet",		no_argument,		0, 'q'},
 			{"runtime",		required_argument,	0, 'r'},
 			{"stop",		required_argument,	0, 's'},
@@ -367,7 +366,7 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv)
 		if (common_parse_options(argc, argv, &params->common))
 			continue;
 
-		c = getopt_long(argc, argv, "a:hH:p:P:qr:s:S:t::T:0:1:2:3:",
+		c = getopt_long(argc, argv, "a:hH:p:qr:s:S:t::T:0:1:2:3:",
 				 long_options, NULL);
 
 		/* Detect the end of the options. */
@@ -402,12 +401,6 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv)
 			if (params->period > 10000000)
 				fatal("Period longer than 10 s");
 			break;
-		case 'P':
-			retval = parse_prio(optarg, &params->common.sched_param);
-			if (retval == -1)
-				fatal("Invalid -P priority");
-			params->common.set_sched = 1;
-			break;
 		case 'q':
 			params->common.quiet = 1;
 			break;
diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/src/timerlat_hist.c
index 4744f84a452e..e7ba083b5eb4 100644
--- a/tools/tracing/rtla/src/timerlat_hist.c
+++ b/tools/tracing/rtla/src/timerlat_hist.c
@@ -802,7 +802,6 @@ static struct common_params
 			{"irq",			required_argument,	0, 'i'},
 			{"nano",		no_argument,		0, 'n'},
 			{"period",		required_argument,	0, 'p'},
-			{"priority",		required_argument,	0, 'P'},
 			{"stack",		required_argument,	0, 's'},
 			{"thread",		required_argument,	0, 'T'},
 			{"trace",		optional_argument,	0, 't'},
@@ -831,7 +830,7 @@ static struct common_params
 		if (common_parse_options(argc, argv, &params->common))
 			continue;
 
-		c = getopt_long(argc, argv, "a:b:E:hH:i:knp:P:s:t::T:uU0123456:7:8:9\1\2:\3:",
+		c = getopt_long(argc, argv, "a:b:E:hH:i:knp:s:t::T:uU0123456:7:8:9\1\2:\3:",
 				 long_options, NULL);
 
 		/* detect the end of the options. */
@@ -890,12 +889,6 @@ static struct common_params
 			if (params->timerlat_period_us > 1000000)
 				fatal("Period longer than 1 s");
 			break;
-		case 'P':
-			retval = parse_prio(optarg, &params->common.sched_param);
-			if (retval == -1)
-				fatal("Invalid -P priority");
-			params->common.set_sched = 1;
-			break;
 		case 's':
 			params->print_stack = get_llong_from_str(optarg);
 			break;
diff --git a/tools/tracing/rtla/src/timerlat_top.c b/tools/tracing/rtla/src/timerlat_top.c
index b77e5b6550a1..8250bea4b2fd 100644
--- a/tools/tracing/rtla/src/timerlat_top.c
+++ b/tools/tracing/rtla/src/timerlat_top.c
@@ -570,7 +570,6 @@ static struct common_params
 			{"irq",			required_argument,	0, 'i'},
 			{"nano",		no_argument,		0, 'n'},
 			{"period",		required_argument,	0, 'p'},
-			{"priority",		required_argument,	0, 'P'},
 			{"quiet",		no_argument,		0, 'q'},
 			{"stack",		required_argument,	0, 's'},
 			{"thread",		required_argument,	0, 'T'},
@@ -595,7 +594,7 @@ static struct common_params
 		if (common_parse_options(argc, argv, &params->common))
 			continue;
 
-		c = getopt_long(argc, argv, "a:hH:i:knp:P:qs:t::T:uU0:1:2:345:6:7:",
+		c = getopt_long(argc, argv, "a:hH:i:knp:qs:t::T:uU0:1:2:345:6:7:",
 				 long_options, NULL);
 
 		/* detect the end of the options. */
@@ -656,12 +655,6 @@ static struct common_params
 			if (params->timerlat_period_us > 1000000)
 				fatal("Period longer than 1 s");
 			break;
-		case 'P':
-			retval = parse_prio(optarg, &params->common.sched_param);
-			if (retval == -1)
-				fatal("Invalid -P priority");
-			params->common.set_sched = 1;
-			break;
 		case 'q':
 			params->common.quiet = 1;
 			break;
-- 
2.51.1


^ permalink raw reply related

* [PATCH v1 6/8] tools/rtla: Consolidate -e/--event option parsing
From: Costa Shulyupin @ 2025-11-21 17:45 UTC (permalink / raw)
  To: Steven Rostedt, Tomas Glozar, Costa Shulyupin, Crystal Wood,
	Wander Lairson Costa, Ivan Pravdin, linux-trace-kernel,
	linux-kernel
In-Reply-To: <20251121174504.519230-1-costa.shul@redhat.com>

Each rtla tool duplicates parsing of -e/--event.

Migrate the option parsing from individual tools to the
common_parse_options().

Signed-off-by: Costa Shulyupin <costa.shul@redhat.com>
---
 tools/tracing/rtla/src/common.c        | 13 ++++++++++++-
 tools/tracing/rtla/src/osnoise_hist.c  | 14 +-------------
 tools/tracing/rtla/src/osnoise_top.c   | 14 +-------------
 tools/tracing/rtla/src/timerlat_hist.c | 14 +-------------
 tools/tracing/rtla/src/timerlat_top.c  | 13 +------------
 5 files changed, 16 insertions(+), 52 deletions(-)

diff --git a/tools/tracing/rtla/src/common.c b/tools/tracing/rtla/src/common.c
index 720add9511e8..6a1675eba96e 100644
--- a/tools/tracing/rtla/src/common.c
+++ b/tools/tracing/rtla/src/common.c
@@ -52,6 +52,7 @@ static void set_signals(struct common_params *params)
  */
 int common_parse_options(int argc, char **argv, struct common_params *common)
 {
+	struct trace_events *tevent;
 	int saved_state = optind;
 	int c;
 
@@ -60,11 +61,12 @@ int common_parse_options(int argc, char **argv, struct common_params *common)
 		{"cgroup",              optional_argument,      0, 'C'},
 		{"debug",               no_argument,            0, 'D'},
 		{"duration",            required_argument,      0, 'd'},
+		{"event",               required_argument,      0, 'e'},
 		{0, 0, 0, 0}
 	};
 
 	opterr = 0;
-	c = getopt_long(argc, argv, "c:C::Dd:", long_options, NULL);
+	c = getopt_long(argc, argv, "c:C::Dd:e:", long_options, NULL);
 
 	switch (c) {
 	case 'c':
@@ -84,6 +86,15 @@ int common_parse_options(int argc, char **argv, struct common_params *common)
 		if (!common->duration)
 			fatal("Invalid -d duration");
 		break;
+	case 'e':
+		tevent = trace_event_alloc(optarg);
+		if (!tevent)
+			fatal("Error alloc trace event");
+
+		if (common->events)
+			tevent->next = common->events;
+		common->events = tevent;
+		break;
 	default:
 		optind = saved_state;
 		return 0;
diff --git a/tools/tracing/rtla/src/osnoise_hist.c b/tools/tracing/rtla/src/osnoise_hist.c
index 1b79bfefc214..c4013f50e803 100644
--- a/tools/tracing/rtla/src/osnoise_hist.c
+++ b/tools/tracing/rtla/src/osnoise_hist.c
@@ -469,7 +469,6 @@ static struct common_params
 *osnoise_hist_parse_args(int argc, char *argv[])
 {
 	struct osnoise_params *params;
-	struct trace_events *tevent;
 	int retval;
 	int c;
 	char *trace_output = NULL;
@@ -499,7 +498,6 @@ static struct common_params
 			{"stop",		required_argument,	0, 's'},
 			{"stop-total",		required_argument,	0, 'S'},
 			{"trace",		optional_argument,	0, 't'},
-			{"event",		required_argument,	0, 'e'},
 			{"threshold",		required_argument,	0, 'T'},
 			{"no-header",		no_argument,		0, '0'},
 			{"no-summary",		no_argument,		0, '1'},
@@ -517,7 +515,7 @@ static struct common_params
 		if (common_parse_options(argc, argv, &params->common))
 			continue;
 
-		c = getopt_long(argc, argv, "a:b:e:E:hH:p:P:r:s:S:t::T:01234:5:6:7:",
+		c = getopt_long(argc, argv, "a:b:E:hH:p:P:r:s:S:t::T:01234:5:6:7:",
 				 long_options, NULL);
 
 		/* detect the end of the options. */
@@ -543,16 +541,6 @@ static struct common_params
 			    params->common.hist.bucket_size >= 1000000)
 				fatal("Bucket size needs to be > 0 and <= 1000000");
 			break;
-		case 'e':
-			tevent = trace_event_alloc(optarg);
-			if (!tevent)
-				fatal("Error alloc trace event");
-
-			if (params->common.events)
-				tevent->next = params->common.events;
-
-			params->common.events = tevent;
-			break;
 		case 'E':
 			params->common.hist.entries = get_llong_from_str(optarg);
 			if (params->common.hist.entries < 10 ||
diff --git a/tools/tracing/rtla/src/osnoise_top.c b/tools/tracing/rtla/src/osnoise_top.c
index 619c5bcf8f35..846d25ee4885 100644
--- a/tools/tracing/rtla/src/osnoise_top.c
+++ b/tools/tracing/rtla/src/osnoise_top.c
@@ -322,7 +322,6 @@ static void osnoise_top_usage(struct osnoise_params *params)
 struct common_params *osnoise_top_parse_args(int argc, char **argv)
 {
 	struct osnoise_params *params;
-	struct trace_events *tevent;
 	int retval;
 	int c;
 	char *trace_output = NULL;
@@ -346,7 +345,6 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv)
 	while (1) {
 		static struct option long_options[] = {
 			{"auto",		required_argument,	0, 'a'},
-			{"event",		required_argument,	0, 'e'},
 			{"house-keeping",	required_argument,	0, 'H'},
 			{"help",		no_argument,		0, 'h'},
 			{"period",		required_argument,	0, 'p'},
@@ -369,7 +367,7 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv)
 		if (common_parse_options(argc, argv, &params->common))
 			continue;
 
-		c = getopt_long(argc, argv, "a:e:hH:p:P:qr:s:S:t::T:0:1:2:3:",
+		c = getopt_long(argc, argv, "a:hH:p:P:qr:s:S:t::T:0:1:2:3:",
 				 long_options, NULL);
 
 		/* Detect the end of the options. */
@@ -388,16 +386,6 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv)
 			if (!trace_output)
 				trace_output = "osnoise_trace.txt";
 
-			break;
-		case 'e':
-			tevent = trace_event_alloc(optarg);
-			if (!tevent)
-				fatal("Error alloc trace event");
-
-			if (params->common.events)
-				tevent->next = params->common.events;
-			params->common.events = tevent;
-
 			break;
 		case 'h':
 		case '?':
diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/src/timerlat_hist.c
index 0a7e5dcce121..4744f84a452e 100644
--- a/tools/tracing/rtla/src/timerlat_hist.c
+++ b/tools/tracing/rtla/src/timerlat_hist.c
@@ -766,7 +766,6 @@ static struct common_params
 *timerlat_hist_parse_args(int argc, char *argv[])
 {
 	struct timerlat_params *params;
-	struct trace_events *tevent;
 	int auto_thresh;
 	int retval;
 	int c;
@@ -810,7 +809,6 @@ static struct common_params
 			{"user-threads",	no_argument,		0, 'u'},
 			{"kernel-threads",	no_argument,		0, 'k'},
 			{"user-load",		no_argument,		0, 'U'},
-			{"event",		required_argument,	0, 'e'},
 			{"no-irq",		no_argument,		0, '0'},
 			{"no-thread",		no_argument,		0, '1'},
 			{"no-header",		no_argument,		0, '2'},
@@ -833,7 +831,7 @@ static struct common_params
 		if (common_parse_options(argc, argv, &params->common))
 			continue;
 
-		c = getopt_long(argc, argv, "a:b:e:E:hH:i:knp:P:s:t::T:uU0123456:7:8:9\1\2:\3:",
+		c = getopt_long(argc, argv, "a:b:E:hH:i:knp:P:s:t::T:uU0123456:7:8:9\1\2:\3:",
 				 long_options, NULL);
 
 		/* detect the end of the options. */
@@ -862,16 +860,6 @@ static struct common_params
 			    params->common.hist.bucket_size >= 1000000)
 				fatal("Bucket size needs to be > 0 and <= 1000000");
 			break;
-		case 'e':
-			tevent = trace_event_alloc(optarg);
-			if (!tevent)
-				fatal("Error alloc trace event");
-
-			if (params->common.events)
-				tevent->next = params->common.events;
-
-			params->common.events = tevent;
-			break;
 		case 'E':
 			params->common.hist.entries = get_llong_from_str(optarg);
 			if (params->common.hist.entries < 10 ||
diff --git a/tools/tracing/rtla/src/timerlat_top.c b/tools/tracing/rtla/src/timerlat_top.c
index 4340fbf3f879..b77e5b6550a1 100644
--- a/tools/tracing/rtla/src/timerlat_top.c
+++ b/tools/tracing/rtla/src/timerlat_top.c
@@ -538,7 +538,6 @@ static struct common_params
 *timerlat_top_parse_args(int argc, char **argv)
 {
 	struct timerlat_params *params;
-	struct trace_events *tevent;
 	long long auto_thresh;
 	int retval;
 	int c;
@@ -566,7 +565,6 @@ static struct common_params
 	while (1) {
 		static struct option long_options[] = {
 			{"auto",		required_argument,	0, 'a'},
-			{"event",		required_argument,	0, 'e'},
 			{"help",		no_argument,		0, 'h'},
 			{"house-keeping",	required_argument,	0, 'H'},
 			{"irq",			required_argument,	0, 'i'},
@@ -597,7 +595,7 @@ static struct common_params
 		if (common_parse_options(argc, argv, &params->common))
 			continue;
 
-		c = getopt_long(argc, argv, "a:e:hH:i:knp:P:qs:t::T:uU0:1:2:345:6:7:",
+		c = getopt_long(argc, argv, "a:hH:i:knp:P:qs:t::T:uU0:1:2:345:6:7:",
 				 long_options, NULL);
 
 		/* detect the end of the options. */
@@ -634,15 +632,6 @@ static struct common_params
 			/* set aa_only to avoid parsing the trace */
 			params->common.aa_only = 1;
 			break;
-		case 'e':
-			tevent = trace_event_alloc(optarg);
-			if (!tevent)
-				fatal("Error alloc trace event");
-
-			if (params->common.events)
-				tevent->next = params->common.events;
-			params->common.events = tevent;
-			break;
 		case 'h':
 		case '?':
 			timerlat_top_usage();
-- 
2.51.1


^ permalink raw reply related

* [PATCH v1 5/8] tools/rtla: Consolidate -d/--duration option parsing
From: Costa Shulyupin @ 2025-11-21 17:45 UTC (permalink / raw)
  To: Steven Rostedt, Tomas Glozar, Costa Shulyupin, Crystal Wood,
	Wander Lairson Costa, Ivan Pravdin, linux-trace-kernel,
	linux-kernel
In-Reply-To: <20251121174504.519230-1-costa.shul@redhat.com>

Each rtla tool duplicates parsing of -d/--duration.

Migrate the option parsing from individual tools to the
common_parse_options().

Signed-off-by: Costa Shulyupin <costa.shul@redhat.com>
---
 tools/tracing/rtla/src/common.c        | 8 +++++++-
 tools/tracing/rtla/src/osnoise_hist.c  | 8 +-------
 tools/tracing/rtla/src/osnoise_top.c   | 8 +-------
 tools/tracing/rtla/src/timerlat_hist.c | 8 +-------
 tools/tracing/rtla/src/timerlat_top.c  | 8 +-------
 5 files changed, 11 insertions(+), 29 deletions(-)

diff --git a/tools/tracing/rtla/src/common.c b/tools/tracing/rtla/src/common.c
index 4d752e438e89..720add9511e8 100644
--- a/tools/tracing/rtla/src/common.c
+++ b/tools/tracing/rtla/src/common.c
@@ -59,11 +59,12 @@ int common_parse_options(int argc, char **argv, struct common_params *common)
 		{"cpus",                required_argument,      0, 'c'},
 		{"cgroup",              optional_argument,      0, 'C'},
 		{"debug",               no_argument,            0, 'D'},
+		{"duration",            required_argument,      0, 'd'},
 		{0, 0, 0, 0}
 	};
 
 	opterr = 0;
-	c = getopt_long(argc, argv, "c:C::D", long_options, NULL);
+	c = getopt_long(argc, argv, "c:C::Dd:", long_options, NULL);
 
 	switch (c) {
 	case 'c':
@@ -78,6 +79,11 @@ int common_parse_options(int argc, char **argv, struct common_params *common)
 	case 'D':
 		config_debug = 1;
 		break;
+	case 'd':
+		common->duration = parse_seconds_duration(optarg);
+		if (!common->duration)
+			fatal("Invalid -d duration");
+		break;
 	default:
 		optind = saved_state;
 		return 0;
diff --git a/tools/tracing/rtla/src/osnoise_hist.c b/tools/tracing/rtla/src/osnoise_hist.c
index 6902486fb144..1b79bfefc214 100644
--- a/tools/tracing/rtla/src/osnoise_hist.c
+++ b/tools/tracing/rtla/src/osnoise_hist.c
@@ -491,7 +491,6 @@ static struct common_params
 			{"auto",		required_argument,	0, 'a'},
 			{"bucket-size",		required_argument,	0, 'b'},
 			{"entries",		required_argument,	0, 'E'},
-			{"duration",		required_argument,	0, 'd'},
 			{"house-keeping",	required_argument,		0, 'H'},
 			{"help",		no_argument,		0, 'h'},
 			{"period",		required_argument,	0, 'p'},
@@ -518,7 +517,7 @@ static struct common_params
 		if (common_parse_options(argc, argv, &params->common))
 			continue;
 
-		c = getopt_long(argc, argv, "a:b:d:e:E:hH:p:P:r:s:S:t::T:01234:5:6:7:",
+		c = getopt_long(argc, argv, "a:b:e:E:hH:p:P:r:s:S:t::T:01234:5:6:7:",
 				 long_options, NULL);
 
 		/* detect the end of the options. */
@@ -544,11 +543,6 @@ static struct common_params
 			    params->common.hist.bucket_size >= 1000000)
 				fatal("Bucket size needs to be > 0 and <= 1000000");
 			break;
-		case 'd':
-			params->common.duration = parse_seconds_duration(optarg);
-			if (!params->common.duration)
-				fatal("Invalid -D duration");
-			break;
 		case 'e':
 			tevent = trace_event_alloc(optarg);
 			if (!tevent)
diff --git a/tools/tracing/rtla/src/osnoise_top.c b/tools/tracing/rtla/src/osnoise_top.c
index 4a61fd50b990..619c5bcf8f35 100644
--- a/tools/tracing/rtla/src/osnoise_top.c
+++ b/tools/tracing/rtla/src/osnoise_top.c
@@ -346,7 +346,6 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv)
 	while (1) {
 		static struct option long_options[] = {
 			{"auto",		required_argument,	0, 'a'},
-			{"duration",		required_argument,	0, 'd'},
 			{"event",		required_argument,	0, 'e'},
 			{"house-keeping",	required_argument,	0, 'H'},
 			{"help",		no_argument,		0, 'h'},
@@ -370,7 +369,7 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv)
 		if (common_parse_options(argc, argv, &params->common))
 			continue;
 
-		c = getopt_long(argc, argv, "a:d:e:hH:p:P:qr:s:S:t::T:0:1:2:3:",
+		c = getopt_long(argc, argv, "a:e:hH:p:P:qr:s:S:t::T:0:1:2:3:",
 				 long_options, NULL);
 
 		/* Detect the end of the options. */
@@ -390,11 +389,6 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv)
 				trace_output = "osnoise_trace.txt";
 
 			break;
-		case 'd':
-			params->common.duration = parse_seconds_duration(optarg);
-			if (!params->common.duration)
-				fatal("Invalid -d duration");
-			break;
 		case 'e':
 			tevent = trace_event_alloc(optarg);
 			if (!tevent)
diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/src/timerlat_hist.c
index 97d20e272583..0a7e5dcce121 100644
--- a/tools/tracing/rtla/src/timerlat_hist.c
+++ b/tools/tracing/rtla/src/timerlat_hist.c
@@ -798,7 +798,6 @@ static struct common_params
 			{"auto",		required_argument,	0, 'a'},
 			{"bucket-size",		required_argument,	0, 'b'},
 			{"entries",		required_argument,	0, 'E'},
-			{"duration",		required_argument,	0, 'd'},
 			{"house-keeping",	required_argument,	0, 'H'},
 			{"help",		no_argument,		0, 'h'},
 			{"irq",			required_argument,	0, 'i'},
@@ -834,7 +833,7 @@ static struct common_params
 		if (common_parse_options(argc, argv, &params->common))
 			continue;
 
-		c = getopt_long(argc, argv, "a:b:d:e:E:hH:i:knp:P:s:t::T:uU0123456:7:8:9\1\2:\3:",
+		c = getopt_long(argc, argv, "a:b:e:E:hH:i:knp:P:s:t::T:uU0123456:7:8:9\1\2:\3:",
 				 long_options, NULL);
 
 		/* detect the end of the options. */
@@ -863,11 +862,6 @@ static struct common_params
 			    params->common.hist.bucket_size >= 1000000)
 				fatal("Bucket size needs to be > 0 and <= 1000000");
 			break;
-		case 'd':
-			params->common.duration = parse_seconds_duration(optarg);
-			if (!params->common.duration)
-				fatal("Invalid -D duration");
-			break;
 		case 'e':
 			tevent = trace_event_alloc(optarg);
 			if (!tevent)
diff --git a/tools/tracing/rtla/src/timerlat_top.c b/tools/tracing/rtla/src/timerlat_top.c
index 96bca67d419f..4340fbf3f879 100644
--- a/tools/tracing/rtla/src/timerlat_top.c
+++ b/tools/tracing/rtla/src/timerlat_top.c
@@ -566,7 +566,6 @@ static struct common_params
 	while (1) {
 		static struct option long_options[] = {
 			{"auto",		required_argument,	0, 'a'},
-			{"duration",		required_argument,	0, 'd'},
 			{"event",		required_argument,	0, 'e'},
 			{"help",		no_argument,		0, 'h'},
 			{"house-keeping",	required_argument,	0, 'H'},
@@ -598,7 +597,7 @@ static struct common_params
 		if (common_parse_options(argc, argv, &params->common))
 			continue;
 
-		c = getopt_long(argc, argv, "a:d:e:hH:i:knp:P:qs:t::T:uU0:1:2:345:6:7:",
+		c = getopt_long(argc, argv, "a:e:hH:i:knp:P:qs:t::T:uU0:1:2:345:6:7:",
 				 long_options, NULL);
 
 		/* detect the end of the options. */
@@ -635,11 +634,6 @@ static struct common_params
 			/* set aa_only to avoid parsing the trace */
 			params->common.aa_only = 1;
 			break;
-		case 'd':
-			params->common.duration = parse_seconds_duration(optarg);
-			if (!params->common.duration)
-				fatal("Invalid -d duration");
-			break;
 		case 'e':
 			tevent = trace_event_alloc(optarg);
 			if (!tevent)
-- 
2.51.1


^ permalink raw reply related

* [PATCH v1 4/8] tools/rtla: Consolidate -D/--debug option parsing
From: Costa Shulyupin @ 2025-11-21 17:45 UTC (permalink / raw)
  To: Steven Rostedt, Tomas Glozar, Costa Shulyupin, Crystal Wood,
	Wander Lairson Costa, Ivan Pravdin, linux-trace-kernel,
	linux-kernel
In-Reply-To: <20251121174504.519230-1-costa.shul@redhat.com>

Each rtla tool duplicates parsing of -D/--debug.

Migrate the option parsing from individual tools to the
common_parse_options().

Signed-off-by: Costa Shulyupin <costa.shul@redhat.com>
---
 tools/tracing/rtla/src/common.c        | 6 +++++-
 tools/tracing/rtla/src/osnoise_hist.c  | 6 +-----
 tools/tracing/rtla/src/osnoise_top.c   | 6 +-----
 tools/tracing/rtla/src/timerlat_hist.c | 6 +-----
 tools/tracing/rtla/src/timerlat_top.c  | 6 +-----
 5 files changed, 9 insertions(+), 21 deletions(-)

diff --git a/tools/tracing/rtla/src/common.c b/tools/tracing/rtla/src/common.c
index 92fb2973c373..4d752e438e89 100644
--- a/tools/tracing/rtla/src/common.c
+++ b/tools/tracing/rtla/src/common.c
@@ -58,11 +58,12 @@ int common_parse_options(int argc, char **argv, struct common_params *common)
 	static struct option long_options[] = {
 		{"cpus",                required_argument,      0, 'c'},
 		{"cgroup",              optional_argument,      0, 'C'},
+		{"debug",               no_argument,            0, 'D'},
 		{0, 0, 0, 0}
 	};
 
 	opterr = 0;
-	c = getopt_long(argc, argv, "c:C::", long_options, NULL);
+	c = getopt_long(argc, argv, "c:C::D", long_options, NULL);
 
 	switch (c) {
 	case 'c':
@@ -74,6 +75,9 @@ int common_parse_options(int argc, char **argv, struct common_params *common)
 		common->cgroup = 1;
 		common->cgroup_name = parse_optional_arg(argc, argv);
 		break;
+	case 'D':
+		config_debug = 1;
+		break;
 	default:
 		optind = saved_state;
 		return 0;
diff --git a/tools/tracing/rtla/src/osnoise_hist.c b/tools/tracing/rtla/src/osnoise_hist.c
index 5cbe5e1f1b07..6902486fb144 100644
--- a/tools/tracing/rtla/src/osnoise_hist.c
+++ b/tools/tracing/rtla/src/osnoise_hist.c
@@ -491,7 +491,6 @@ static struct common_params
 			{"auto",		required_argument,	0, 'a'},
 			{"bucket-size",		required_argument,	0, 'b'},
 			{"entries",		required_argument,	0, 'E'},
-			{"debug",		no_argument,		0, 'D'},
 			{"duration",		required_argument,	0, 'd'},
 			{"house-keeping",	required_argument,		0, 'H'},
 			{"help",		no_argument,		0, 'h'},
@@ -519,7 +518,7 @@ static struct common_params
 		if (common_parse_options(argc, argv, &params->common))
 			continue;
 
-		c = getopt_long(argc, argv, "a:b:d:e:E:DhH:p:P:r:s:S:t::T:01234:5:6:7:",
+		c = getopt_long(argc, argv, "a:b:d:e:E:hH:p:P:r:s:S:t::T:01234:5:6:7:",
 				 long_options, NULL);
 
 		/* detect the end of the options. */
@@ -545,9 +544,6 @@ static struct common_params
 			    params->common.hist.bucket_size >= 1000000)
 				fatal("Bucket size needs to be > 0 and <= 1000000");
 			break;
-		case 'D':
-			config_debug = 1;
-			break;
 		case 'd':
 			params->common.duration = parse_seconds_duration(optarg);
 			if (!params->common.duration)
diff --git a/tools/tracing/rtla/src/osnoise_top.c b/tools/tracing/rtla/src/osnoise_top.c
index 35db5b73c0d7..4a61fd50b990 100644
--- a/tools/tracing/rtla/src/osnoise_top.c
+++ b/tools/tracing/rtla/src/osnoise_top.c
@@ -346,7 +346,6 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv)
 	while (1) {
 		static struct option long_options[] = {
 			{"auto",		required_argument,	0, 'a'},
-			{"debug",		no_argument,		0, 'D'},
 			{"duration",		required_argument,	0, 'd'},
 			{"event",		required_argument,	0, 'e'},
 			{"house-keeping",	required_argument,	0, 'H'},
@@ -371,7 +370,7 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv)
 		if (common_parse_options(argc, argv, &params->common))
 			continue;
 
-		c = getopt_long(argc, argv, "a:d:De:hH:p:P:qr:s:S:t::T:0:1:2:3:",
+		c = getopt_long(argc, argv, "a:d:e:hH:p:P:qr:s:S:t::T:0:1:2:3:",
 				 long_options, NULL);
 
 		/* Detect the end of the options. */
@@ -390,9 +389,6 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv)
 			if (!trace_output)
 				trace_output = "osnoise_trace.txt";
 
-			break;
-		case 'D':
-			config_debug = 1;
 			break;
 		case 'd':
 			params->common.duration = parse_seconds_duration(optarg);
diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/src/timerlat_hist.c
index 9ecab2bb0f1e..97d20e272583 100644
--- a/tools/tracing/rtla/src/timerlat_hist.c
+++ b/tools/tracing/rtla/src/timerlat_hist.c
@@ -797,7 +797,6 @@ static struct common_params
 		static struct option long_options[] = {
 			{"auto",		required_argument,	0, 'a'},
 			{"bucket-size",		required_argument,	0, 'b'},
-			{"debug",		no_argument,		0, 'D'},
 			{"entries",		required_argument,	0, 'E'},
 			{"duration",		required_argument,	0, 'd'},
 			{"house-keeping",	required_argument,	0, 'H'},
@@ -835,7 +834,7 @@ static struct common_params
 		if (common_parse_options(argc, argv, &params->common))
 			continue;
 
-		c = getopt_long(argc, argv, "a:b:d:e:E:DhH:i:knp:P:s:t::T:uU0123456:7:8:9\1\2:\3:",
+		c = getopt_long(argc, argv, "a:b:d:e:E:hH:i:knp:P:s:t::T:uU0123456:7:8:9\1\2:\3:",
 				 long_options, NULL);
 
 		/* detect the end of the options. */
@@ -864,9 +863,6 @@ static struct common_params
 			    params->common.hist.bucket_size >= 1000000)
 				fatal("Bucket size needs to be > 0 and <= 1000000");
 			break;
-		case 'D':
-			config_debug = 1;
-			break;
 		case 'd':
 			params->common.duration = parse_seconds_duration(optarg);
 			if (!params->common.duration)
diff --git a/tools/tracing/rtla/src/timerlat_top.c b/tools/tracing/rtla/src/timerlat_top.c
index 6329c3a489aa..96bca67d419f 100644
--- a/tools/tracing/rtla/src/timerlat_top.c
+++ b/tools/tracing/rtla/src/timerlat_top.c
@@ -566,7 +566,6 @@ static struct common_params
 	while (1) {
 		static struct option long_options[] = {
 			{"auto",		required_argument,	0, 'a'},
-			{"debug",		no_argument,		0, 'D'},
 			{"duration",		required_argument,	0, 'd'},
 			{"event",		required_argument,	0, 'e'},
 			{"help",		no_argument,		0, 'h'},
@@ -599,7 +598,7 @@ static struct common_params
 		if (common_parse_options(argc, argv, &params->common))
 			continue;
 
-		c = getopt_long(argc, argv, "a:d:De:hH:i:knp:P:qs:t::T:uU0:1:2:345:6:7:",
+		c = getopt_long(argc, argv, "a:d:e:hH:i:knp:P:qs:t::T:uU0:1:2:345:6:7:",
 				 long_options, NULL);
 
 		/* detect the end of the options. */
@@ -636,9 +635,6 @@ static struct common_params
 			/* set aa_only to avoid parsing the trace */
 			params->common.aa_only = 1;
 			break;
-		case 'D':
-			config_debug = 1;
-			break;
 		case 'd':
 			params->common.duration = parse_seconds_duration(optarg);
 			if (!params->common.duration)
-- 
2.51.1


^ permalink raw reply related

* [PATCH v1 3/8] tools/rtla: Consolidate -C/--cgroup option parsing
From: Costa Shulyupin @ 2025-11-21 17:44 UTC (permalink / raw)
  To: Steven Rostedt, Tomas Glozar, Costa Shulyupin, Crystal Wood,
	Wander Lairson Costa, Ivan Pravdin, linux-trace-kernel,
	linux-kernel
In-Reply-To: <20251121174504.519230-1-costa.shul@redhat.com>

Each rtla tool duplicates parsing of -C/--cgroup.

Migrate the option parsing from individual tools to the
common_parse_options().

Signed-off-by: Costa Shulyupin <costa.shul@redhat.com>
---
 tools/tracing/rtla/src/common.c        | 7 ++++++-
 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 +------
 5 files changed, 10 insertions(+), 25 deletions(-)

diff --git a/tools/tracing/rtla/src/common.c b/tools/tracing/rtla/src/common.c
index e12192fcb3ab..92fb2973c373 100644
--- a/tools/tracing/rtla/src/common.c
+++ b/tools/tracing/rtla/src/common.c
@@ -57,11 +57,12 @@ int common_parse_options(int argc, char **argv, struct common_params *common)
 
 	static struct option long_options[] = {
 		{"cpus",                required_argument,      0, 'c'},
+		{"cgroup",              optional_argument,      0, 'C'},
 		{0, 0, 0, 0}
 	};
 
 	opterr = 0;
-	c = getopt_long(argc, argv, "c:", long_options, NULL);
+	c = getopt_long(argc, argv, "c:C::", long_options, NULL);
 
 	switch (c) {
 	case 'c':
@@ -69,6 +70,10 @@ int common_parse_options(int argc, char **argv, struct common_params *common)
 			fatal("Invalid -c cpu list");
 		common->cpus = optarg;
 		break;
+	case 'C':
+		common->cgroup = 1;
+		common->cgroup_name = parse_optional_arg(argc, argv);
+		break;
 	default:
 		optind = saved_state;
 		return 0;
diff --git a/tools/tracing/rtla/src/osnoise_hist.c b/tools/tracing/rtla/src/osnoise_hist.c
index 9e721362989a..5cbe5e1f1b07 100644
--- a/tools/tracing/rtla/src/osnoise_hist.c
+++ b/tools/tracing/rtla/src/osnoise_hist.c
@@ -491,7 +491,6 @@ static struct common_params
 			{"auto",		required_argument,	0, 'a'},
 			{"bucket-size",		required_argument,	0, 'b'},
 			{"entries",		required_argument,	0, 'E'},
-			{"cgroup",		optional_argument,	0, 'C'},
 			{"debug",		no_argument,		0, 'D'},
 			{"duration",		required_argument,	0, 'd'},
 			{"house-keeping",	required_argument,		0, 'H'},
@@ -520,7 +519,7 @@ static struct common_params
 		if (common_parse_options(argc, argv, &params->common))
 			continue;
 
-		c = getopt_long(argc, argv, "a:C::b:d:e:E:DhH:p:P:r:s:S:t::T:01234:5:6:7:",
+		c = getopt_long(argc, argv, "a:b:d:e:E:DhH:p:P:r:s:S:t::T:01234:5:6:7:",
 				 long_options, NULL);
 
 		/* detect the end of the options. */
@@ -546,10 +545,6 @@ static struct common_params
 			    params->common.hist.bucket_size >= 1000000)
 				fatal("Bucket size needs to be > 0 and <= 1000000");
 			break;
-		case 'C':
-			params->common.cgroup = 1;
-			params->common.cgroup_name = parse_optional_arg(argc, argv);
-			break;
 		case 'D':
 			config_debug = 1;
 			break;
diff --git a/tools/tracing/rtla/src/osnoise_top.c b/tools/tracing/rtla/src/osnoise_top.c
index 73736cefd992..35db5b73c0d7 100644
--- a/tools/tracing/rtla/src/osnoise_top.c
+++ b/tools/tracing/rtla/src/osnoise_top.c
@@ -346,7 +346,6 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv)
 	while (1) {
 		static struct option long_options[] = {
 			{"auto",		required_argument,	0, 'a'},
-			{"cgroup",		optional_argument,	0, 'C'},
 			{"debug",		no_argument,		0, 'D'},
 			{"duration",		required_argument,	0, 'd'},
 			{"event",		required_argument,	0, 'e'},
@@ -372,7 +371,7 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv)
 		if (common_parse_options(argc, argv, &params->common))
 			continue;
 
-		c = getopt_long(argc, argv, "a:C::d:De:hH:p:P:qr:s:S:t::T:0:1:2:3:",
+		c = getopt_long(argc, argv, "a:d:De:hH:p:P:qr:s:S:t::T:0:1:2:3:",
 				 long_options, NULL);
 
 		/* Detect the end of the options. */
@@ -391,10 +390,6 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv)
 			if (!trace_output)
 				trace_output = "osnoise_trace.txt";
 
-			break;
-		case 'C':
-			params->common.cgroup = 1;
-			params->common.cgroup_name = parse_optional_arg(argc, argv);
 			break;
 		case 'D':
 			config_debug = 1;
diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/src/timerlat_hist.c
index 4ae77145adea..9ecab2bb0f1e 100644
--- a/tools/tracing/rtla/src/timerlat_hist.c
+++ b/tools/tracing/rtla/src/timerlat_hist.c
@@ -796,7 +796,6 @@ static struct common_params
 	while (1) {
 		static struct option long_options[] = {
 			{"auto",		required_argument,	0, 'a'},
-			{"cgroup",		optional_argument,	0, 'C'},
 			{"bucket-size",		required_argument,	0, 'b'},
 			{"debug",		no_argument,		0, 'D'},
 			{"entries",		required_argument,	0, 'E'},
@@ -836,7 +835,7 @@ static struct common_params
 		if (common_parse_options(argc, argv, &params->common))
 			continue;
 
-		c = getopt_long(argc, argv, "a:C::b:d:e:E:DhH:i:knp:P:s:t::T:uU0123456:7:8:9\1\2:\3:",
+		c = getopt_long(argc, argv, "a:b:d:e:E:DhH:i:knp:P:s:t::T:uU0123456:7:8:9\1\2:\3:",
 				 long_options, NULL);
 
 		/* detect the end of the options. */
@@ -858,10 +857,6 @@ static struct common_params
 			if (!trace_output)
 				trace_output = "timerlat_trace.txt";
 
-			break;
-		case 'C':
-			params->common.cgroup = 1;
-			params->common.cgroup_name = parse_optional_arg(argc, argv);
 			break;
 		case 'b':
 			params->common.hist.bucket_size = get_llong_from_str(optarg);
diff --git a/tools/tracing/rtla/src/timerlat_top.c b/tools/tracing/rtla/src/timerlat_top.c
index 9774c26b27ff..6329c3a489aa 100644
--- a/tools/tracing/rtla/src/timerlat_top.c
+++ b/tools/tracing/rtla/src/timerlat_top.c
@@ -566,7 +566,6 @@ static struct common_params
 	while (1) {
 		static struct option long_options[] = {
 			{"auto",		required_argument,	0, 'a'},
-			{"cgroup",		optional_argument,	0, 'C'},
 			{"debug",		no_argument,		0, 'D'},
 			{"duration",		required_argument,	0, 'd'},
 			{"event",		required_argument,	0, 'e'},
@@ -600,7 +599,7 @@ static struct common_params
 		if (common_parse_options(argc, argv, &params->common))
 			continue;
 
-		c = getopt_long(argc, argv, "a:C::d:De:hH:i:knp:P:qs:t::T:uU0:1:2:345:6:7:",
+		c = getopt_long(argc, argv, "a:d:De:hH:i:knp:P:qs:t::T:uU0:1:2:345:6:7:",
 				 long_options, NULL);
 
 		/* detect the end of the options. */
@@ -637,10 +636,6 @@ static struct common_params
 			/* set aa_only to avoid parsing the trace */
 			params->common.aa_only = 1;
 			break;
-		case 'C':
-			params->common.cgroup = 1;
-			params->common.cgroup_name = optarg;
-			break;
 		case 'D':
 			config_debug = 1;
 			break;
-- 
2.51.1


^ permalink raw reply related

* [PATCH v1 2/8] tools/rtla: Consolidate -c/--cpus option parsing
From: Costa Shulyupin @ 2025-11-21 17:44 UTC (permalink / raw)
  To: Steven Rostedt, Tomas Glozar, Costa Shulyupin, Crystal Wood,
	Wander Lairson Costa, Ivan Pravdin, linux-trace-kernel,
	linux-kernel
In-Reply-To: <20251121174504.519230-1-costa.shul@redhat.com>

Each rtla tool duplicates parsing of -c/--cpus.

Migrate the option parsing from individual tools to the
common_parse_options().

Signed-off-by: Costa Shulyupin <costa.shul@redhat.com>
---
 tools/tracing/rtla/src/common.c        | 8 +++++++-
 tools/tracing/rtla/src/osnoise_hist.c  | 9 +--------
 tools/tracing/rtla/src/osnoise_top.c   | 9 +--------
 tools/tracing/rtla/src/timerlat_hist.c | 9 +--------
 tools/tracing/rtla/src/timerlat_top.c  | 9 +--------
 5 files changed, 11 insertions(+), 33 deletions(-)

diff --git a/tools/tracing/rtla/src/common.c b/tools/tracing/rtla/src/common.c
index 5eaf6d9e11bf..e12192fcb3ab 100644
--- a/tools/tracing/rtla/src/common.c
+++ b/tools/tracing/rtla/src/common.c
@@ -56,13 +56,19 @@ int common_parse_options(int argc, char **argv, struct common_params *common)
 	int c;
 
 	static struct option long_options[] = {
+		{"cpus",                required_argument,      0, 'c'},
 		{0, 0, 0, 0}
 	};
 
 	opterr = 0;
-	c = getopt_long(argc, argv, "", long_options, NULL);
+	c = getopt_long(argc, argv, "c:", long_options, NULL);
 
 	switch (c) {
+	case 'c':
+		if (parse_cpu_set(optarg, &common->monitored_cpus))
+			fatal("Invalid -c cpu list");
+		common->cpus = optarg;
+		break;
 	default:
 		optind = saved_state;
 		return 0;
diff --git a/tools/tracing/rtla/src/osnoise_hist.c b/tools/tracing/rtla/src/osnoise_hist.c
index 35f4a068af95..9e721362989a 100644
--- a/tools/tracing/rtla/src/osnoise_hist.c
+++ b/tools/tracing/rtla/src/osnoise_hist.c
@@ -491,7 +491,6 @@ static struct common_params
 			{"auto",		required_argument,	0, 'a'},
 			{"bucket-size",		required_argument,	0, 'b'},
 			{"entries",		required_argument,	0, 'E'},
-			{"cpus",		required_argument,	0, 'c'},
 			{"cgroup",		optional_argument,	0, 'C'},
 			{"debug",		no_argument,		0, 'D'},
 			{"duration",		required_argument,	0, 'd'},
@@ -521,7 +520,7 @@ static struct common_params
 		if (common_parse_options(argc, argv, &params->common))
 			continue;
 
-		c = getopt_long(argc, argv, "a:c:C::b:d:e:E:DhH:p:P:r:s:S:t::T:01234:5:6:7:",
+		c = getopt_long(argc, argv, "a:C::b:d:e:E:DhH:p:P:r:s:S:t::T:01234:5:6:7:",
 				 long_options, NULL);
 
 		/* detect the end of the options. */
@@ -547,12 +546,6 @@ static struct common_params
 			    params->common.hist.bucket_size >= 1000000)
 				fatal("Bucket size needs to be > 0 and <= 1000000");
 			break;
-		case 'c':
-			retval = parse_cpu_set(optarg, &params->common.monitored_cpus);
-			if (retval)
-				fatal("Invalid -c cpu list");
-			params->common.cpus = optarg;
-			break;
 		case 'C':
 			params->common.cgroup = 1;
 			params->common.cgroup_name = parse_optional_arg(argc, argv);
diff --git a/tools/tracing/rtla/src/osnoise_top.c b/tools/tracing/rtla/src/osnoise_top.c
index 550731c7addd..73736cefd992 100644
--- a/tools/tracing/rtla/src/osnoise_top.c
+++ b/tools/tracing/rtla/src/osnoise_top.c
@@ -346,7 +346,6 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv)
 	while (1) {
 		static struct option long_options[] = {
 			{"auto",		required_argument,	0, 'a'},
-			{"cpus",		required_argument,	0, 'c'},
 			{"cgroup",		optional_argument,	0, 'C'},
 			{"debug",		no_argument,		0, 'D'},
 			{"duration",		required_argument,	0, 'd'},
@@ -373,7 +372,7 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv)
 		if (common_parse_options(argc, argv, &params->common))
 			continue;
 
-		c = getopt_long(argc, argv, "a:c:C::d:De:hH:p:P:qr:s:S:t::T:0:1:2:3:",
+		c = getopt_long(argc, argv, "a:C::d:De:hH:p:P:qr:s:S:t::T:0:1:2:3:",
 				 long_options, NULL);
 
 		/* Detect the end of the options. */
@@ -392,12 +391,6 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv)
 			if (!trace_output)
 				trace_output = "osnoise_trace.txt";
 
-			break;
-		case 'c':
-			retval = parse_cpu_set(optarg, &params->common.monitored_cpus);
-			if (retval)
-				fatal("Invalid -c cpu list");
-			params->common.cpus = optarg;
 			break;
 		case 'C':
 			params->common.cgroup = 1;
diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/src/timerlat_hist.c
index ffcfcabb9964..4ae77145adea 100644
--- a/tools/tracing/rtla/src/timerlat_hist.c
+++ b/tools/tracing/rtla/src/timerlat_hist.c
@@ -796,7 +796,6 @@ static struct common_params
 	while (1) {
 		static struct option long_options[] = {
 			{"auto",		required_argument,	0, 'a'},
-			{"cpus",		required_argument,	0, 'c'},
 			{"cgroup",		optional_argument,	0, 'C'},
 			{"bucket-size",		required_argument,	0, 'b'},
 			{"debug",		no_argument,		0, 'D'},
@@ -837,7 +836,7 @@ static struct common_params
 		if (common_parse_options(argc, argv, &params->common))
 			continue;
 
-		c = getopt_long(argc, argv, "a:c:C::b:d:e:E:DhH:i:knp:P:s:t::T:uU0123456:7:8:9\1\2:\3:",
+		c = getopt_long(argc, argv, "a:C::b:d:e:E:DhH:i:knp:P:s:t::T:uU0123456:7:8:9\1\2:\3:",
 				 long_options, NULL);
 
 		/* detect the end of the options. */
@@ -859,12 +858,6 @@ static struct common_params
 			if (!trace_output)
 				trace_output = "timerlat_trace.txt";
 
-			break;
-		case 'c':
-			retval = parse_cpu_set(optarg, &params->common.monitored_cpus);
-			if (retval)
-				fatal("Invalid -c cpu list");
-			params->common.cpus = optarg;
 			break;
 		case 'C':
 			params->common.cgroup = 1;
diff --git a/tools/tracing/rtla/src/timerlat_top.c b/tools/tracing/rtla/src/timerlat_top.c
index d18d48671ccd..9774c26b27ff 100644
--- a/tools/tracing/rtla/src/timerlat_top.c
+++ b/tools/tracing/rtla/src/timerlat_top.c
@@ -566,7 +566,6 @@ static struct common_params
 	while (1) {
 		static struct option long_options[] = {
 			{"auto",		required_argument,	0, 'a'},
-			{"cpus",		required_argument,	0, 'c'},
 			{"cgroup",		optional_argument,	0, 'C'},
 			{"debug",		no_argument,		0, 'D'},
 			{"duration",		required_argument,	0, 'd'},
@@ -601,7 +600,7 @@ static struct common_params
 		if (common_parse_options(argc, argv, &params->common))
 			continue;
 
-		c = getopt_long(argc, argv, "a:c:C::d:De:hH:i:knp:P:qs:t::T:uU0:1:2:345:6:7:",
+		c = getopt_long(argc, argv, "a:C::d:De:hH:i:knp:P:qs:t::T:uU0:1:2:345:6:7:",
 				 long_options, NULL);
 
 		/* detect the end of the options. */
@@ -638,12 +637,6 @@ static struct common_params
 			/* set aa_only to avoid parsing the trace */
 			params->common.aa_only = 1;
 			break;
-		case 'c':
-			retval = parse_cpu_set(optarg, &params->common.monitored_cpus);
-			if (retval)
-				fatal("Invalid -c cpu list");
-			params->common.cpus = optarg;
-			break;
 		case 'C':
 			params->common.cgroup = 1;
 			params->common.cgroup_name = optarg;
-- 
2.51.1


^ permalink raw reply related

* [PATCH v1 1/8] tools/rtla: Add common_parse_options()
From: Costa Shulyupin @ 2025-11-21 17:44 UTC (permalink / raw)
  To: Steven Rostedt, Tomas Glozar, Costa Shulyupin, Crystal Wood,
	Wander Lairson Costa, Ivan Pravdin, linux-trace-kernel,
	linux-kernel
In-Reply-To: <20251121174504.519230-1-costa.shul@redhat.com>

Each rtla tool duplicates parsing of many common options. This creates
maintenance overhead and risks inconsistencies when updating these
options.

Add common_parse_options() to centralize parsing of options used across
all tools.

Common options to be migrated in future patches.

Signed-off-by: Costa Shulyupin <costa.shul@redhat.com>
---
 tools/tracing/rtla/src/common.c        | 34 ++++++++++++++++++++++++++
 tools/tracing/rtla/src/common.h        |  1 +
 tools/tracing/rtla/src/osnoise_hist.c  |  3 +++
 tools/tracing/rtla/src/osnoise_top.c   |  3 +++
 tools/tracing/rtla/src/timerlat_hist.c |  3 +++
 tools/tracing/rtla/src/timerlat_top.c  |  3 +++
 6 files changed, 47 insertions(+)

diff --git a/tools/tracing/rtla/src/common.c b/tools/tracing/rtla/src/common.c
index b197037fc58b..5eaf6d9e11bf 100644
--- a/tools/tracing/rtla/src/common.c
+++ b/tools/tracing/rtla/src/common.c
@@ -5,6 +5,7 @@
 #include <signal.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <getopt.h>
 #include "common.h"
 
 struct trace_instance *trace_inst;
@@ -37,6 +38,39 @@ static void set_signals(struct common_params *params)
 	}
 }
 
+/*
+ * common_parse_options - parse common command line options
+ *
+ * @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.
+ */
+int common_parse_options(int argc, char **argv, struct common_params *common)
+{
+	int saved_state = optind;
+	int c;
+
+	static struct option long_options[] = {
+		{0, 0, 0, 0}
+	};
+
+	opterr = 0;
+	c = getopt_long(argc, argv, "", long_options, NULL);
+
+	switch (c) {
+	default:
+		optind = saved_state;
+		return 0;
+	}
+
+	return c;
+}
+
 /*
  * common_apply_config - apply common configs to the initialized tool
  */
diff --git a/tools/tracing/rtla/src/common.h b/tools/tracing/rtla/src/common.h
index 9ec2b7632c37..1066d777a823 100644
--- a/tools/tracing/rtla/src/common.h
+++ b/tools/tracing/rtla/src/common.h
@@ -153,6 +153,7 @@ struct osnoise_tool *osnoise_init_tool(char *tool_name);
 struct osnoise_tool *osnoise_init_trace_tool(const char *tracer);
 bool osnoise_trace_is_off(struct osnoise_tool *tool, struct osnoise_tool *record);
 
+int common_parse_options(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 ff8c231e47c4..35f4a068af95 100644
--- a/tools/tracing/rtla/src/osnoise_hist.c
+++ b/tools/tracing/rtla/src/osnoise_hist.c
@@ -518,6 +518,9 @@ static struct common_params
 			{0, 0, 0, 0}
 		};
 
+		if (common_parse_options(argc, argv, &params->common))
+			continue;
+
 		c = getopt_long(argc, argv, "a:c:C::b:d:e:E:DhH:p:P:r:s:S:t::T:01234:5:6:7:",
 				 long_options, NULL);
 
diff --git a/tools/tracing/rtla/src/osnoise_top.c b/tools/tracing/rtla/src/osnoise_top.c
index 04c699bdd736..550731c7addd 100644
--- a/tools/tracing/rtla/src/osnoise_top.c
+++ b/tools/tracing/rtla/src/osnoise_top.c
@@ -370,6 +370,9 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv)
 			{0, 0, 0, 0}
 		};
 
+		if (common_parse_options(argc, argv, &params->common))
+			continue;
+
 		c = getopt_long(argc, argv, "a:c:C::d:De:hH:p:P:qr:s:S:t::T:0:1:2:3:",
 				 long_options, NULL);
 
diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/src/timerlat_hist.c
index 1fb471a787b7..ffcfcabb9964 100644
--- a/tools/tracing/rtla/src/timerlat_hist.c
+++ b/tools/tracing/rtla/src/timerlat_hist.c
@@ -834,6 +834,9 @@ static struct common_params
 			{0, 0, 0, 0}
 		};
 
+		if (common_parse_options(argc, argv, &params->common))
+			continue;
+
 		c = getopt_long(argc, argv, "a:c:C::b:d:e:E:DhH:i:knp:P:s:t::T:uU0123456:7:8:9\1\2:\3:",
 				 long_options, NULL);
 
diff --git a/tools/tracing/rtla/src/timerlat_top.c b/tools/tracing/rtla/src/timerlat_top.c
index 29c2c1f717ed..d18d48671ccd 100644
--- a/tools/tracing/rtla/src/timerlat_top.c
+++ b/tools/tracing/rtla/src/timerlat_top.c
@@ -598,6 +598,9 @@ static struct common_params
 			{0, 0, 0, 0}
 		};
 
+		if (common_parse_options(argc, argv, &params->common))
+			continue;
+
 		c = getopt_long(argc, argv, "a:c:C::d:De:hH:i:knp:P:qs:t::T:uU0:1:2:345:6:7:",
 				 long_options, NULL);
 
-- 
2.51.1


^ permalink raw reply related

* [PATCH v1 0/8] tools/rtla: Consolidate common command line options
From: Costa Shulyupin @ 2025-11-21 17:44 UTC (permalink / raw)
  To: Steven Rostedt, Tomas Glozar, Costa Shulyupin, Crystal Wood,
	Wander Lairson Costa, Ivan Pravdin, linux-trace-kernel,
	linux-kernel

Argument parsing functions are the longest functions of the project:

lizard --warnings_only --sort nloc -L100 | head -n 4
./src/timerlat_hist.c:766: warning: timerlat_hist_parse_args has 247 NLOC, 76 CCN, 1579 token, 1 PARAM, 287 length, 0 ND
./src/timerlat_top.c:538: warning: timerlat_top_parse_args has 217 NLOC, 64 CCN, 1338 token, 2 PARAM, 262 length, 0 ND
./src/osnoise_hist.c:469: warning: osnoise_hist_parse_args has 195 NLOC, 56 CCN, 1225 token, 1 PARAM, 216 length, 0 ND
./src/osnoise_top.c:322: warning: osnoise_top_parse_args has 169 NLOC, 46 CCN, 1019 token, 2 PARAM, 191 length, 0 ND

Moreover, they contain a lot of duplicate code and growing.

Refactor these functions to reduce code duplication.

Benefits:
- Single implementation for common options
- Easier maintenance and consistent behavior

Costa Shulyupin (8):
  tools/rtla: Add common_parse_options()
  tools/rtla: Consolidate -c/--cpus option parsing
  tools/rtla: Consolidate -C/--cgroup option parsing
  tools/rtla: Consolidate -D/--debug option parsing
  tools/rtla: Consolidate -d/--duration option parsing
  tools/rtla: Consolidate -e/--event option parsing
  tools/rtla: Consolidate -P/--priority option parsing
  tools/rtla: Consolidate -H/--house-keeping option parsing

 tools/tracing/rtla/src/common.c        | 78 ++++++++++++++++++++++++++
 tools/tracing/rtla/src/common.h        |  1 +
 tools/tracing/rtla/src/osnoise_hist.c  | 53 ++---------------
 tools/tracing/rtla/src/osnoise_top.c   | 53 ++---------------
 tools/tracing/rtla/src/timerlat_hist.c | 53 ++---------------
 tools/tracing/rtla/src/timerlat_top.c  | 52 ++---------------
 6 files changed, 95 insertions(+), 195 deletions(-)

-- 
2.51.1


^ permalink raw reply

* Re: [RFC PATCH v7 30/31] x86/mm, mm/vmalloc: Defer kernel TLB flush IPIs under CONFIG_COALESCE_TLBI=y
From: Valentin Schneider @ 2025-11-21 17:37 UTC (permalink / raw)
  To: Dave Hansen, linux-kernel, linux-mm, rcu, x86, linux-arm-kernel,
	loongarch, linux-riscv, linux-arch, linux-trace-kernel
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
	H. Peter Anvin, Andy Lutomirski, Peter Zijlstra,
	Arnaldo Carvalho de Melo, Josh Poimboeuf, Paolo Bonzini,
	Arnd Bergmann, Frederic Weisbecker, Paul E. McKenney, Jason Baron,
	Steven Rostedt, Ard Biesheuvel, Sami Tolvanen, David S. Miller,
	Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Boqun Feng,
	Uladzislau Rezki, Mathieu Desnoyers, Mel Gorman, Andrew Morton,
	Masahiro Yamada, Han Shen, Rik van Riel, Jann Horn, Dan Carpenter,
	Oleg Nesterov, Juri Lelli, Clark Williams, Yair Podemsky,
	Marcelo Tosatti, Daniel Wagner, Petr Tesarik, Shrikanth Hegde
In-Reply-To: <bad9eaaa-561a-498a-90d1-fe3a3ab8ba37@intel.com>

On 19/11/25 10:31, Dave Hansen wrote:
> On 11/14/25 07:14, Valentin Schneider wrote:
>> +static bool flush_tlb_kernel_cond(int cpu, void *info)
>> +{
>> +	return housekeeping_cpu(cpu, HK_TYPE_KERNEL_NOISE) ||
>> +	       per_cpu(kernel_cr3_loaded, cpu);
>> +}
>
> Is it OK that 'kernel_cr3_loaded' can be be stale? Since it's not part
> of the instruction that actually sets CR3, there's a window between when
> 'kernel_cr3_loaded' is set (or cleared) and CR3 is actually written.
>
> Is that OK?
>
> It seems like it could lead to both unnecessary IPIs being sent and for
> IPIs to be missed.
>

So the pattern is

  SWITCH_TO_KERNEL_CR3
  FLUSH
  KERNEL_CR3_LOADED := 1

  KERNEL_CR3_LOADED := 0
  SWITCH_TO_USER_CR3


The 0 -> 1 transition has a window between the unconditional flush and the
write to 1 where a remote flush IPI may be omitted. Given that the write is
immediately following the unconditional flush, that would really be just
two flushes racing with each other, but I could punt the kernel_cr3_loaded
write above the unconditional flush.

The 1 -> 0 transition is less problematic, worst case a remote flush races
with the CPU returning to userspace and it'll get interrupted back to
kernelspace.


^ permalink raw reply

* Re: [PATCH v4 4/9] mm: implement sticky VMA flags
From: David Hildenbrand (Red Hat) @ 2025-11-21 16:09 UTC (permalink / raw)
  To: Lorenzo Stoakes, Andrew Morton
  Cc: Jonathan Corbet, Liam R . Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Steven Rostedt,
	Masami Hiramatsu, Mathieu Desnoyers, Jann Horn, Pedro Falcato,
	Zi Yan, Baolin Wang, Nico Pache, Ryan Roberts, Dev Jain,
	Barry Song, Lance Yang, linux-kernel, linux-fsdevel, linux-doc,
	linux-mm, linux-trace-kernel, linux-kselftest, Andrei Vagin
In-Reply-To: <22ad5269f7669d62afb42ce0c79bad70b994c58d.1763460113.git.lorenzo.stoakes@oracle.com>

On 11/18/25 11:17, Lorenzo Stoakes wrote:
> It is useful to be able to designate that certain flags are 'sticky', that
> is, if two VMAs are merged one with a flag of this nature and one without,
> the merged VMA sets this flag.
> 
> As a result we ignore these flags for the purposes of determining VMA flag
> differences between VMAs being considered for merge.
> 
> This patch therefore updates the VMA merge logic to perform this action,
> with flags possessing this property being described in the VM_STICKY
> bitmap.
> 
> Those flags which ought to be ignored for the purposes of VMA merge are
> described in the VM_IGNORE_MERGE bitmap, which the VMA merge logic is also
> updated to use.
> 
> As part of this change we place VM_SOFTDIRTY in VM_IGNORE_MERGE as it
> already had this behaviour, alongside VM_STICKY as sticky flags by
> implication must not disallow merge.
> 
> Ultimately it seems that we should make VM_SOFTDIRTY a sticky flag in its
> own right, but this change is out of scope for this series.
> 
> The only sticky flag designated as such is VM_MAYBE_GUARD, so as a result
> of this change, once the VMA flag is set upon guard region installation,
> VMAs with guard ranges will now not have their merge behaviour impacted as
> a result and can be freely merged with other VMAs without VM_MAYBE_GUARD
> set.
> 
> Also update the comments for vma_modify_flags() to directly reference
> sticky flags now we have established the concept.
> 
> We also update the VMA userland tests to account for the changes.
> 
> Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
> Reviewed-by: Pedro Falcato <pfalcato@suse.de>
> Reviewed-by: Vlastimil Babka <vbabka@suse.cz>
> ---

Acked-by: David Hildenbrand (Red Hat) <david@kernel.org>

-- 
Cheers

David

^ permalink raw reply

* Re: [PATCH 3/3] tracing: Use strim() in trigger_process_regex() instead of skip_spaces()
From: Masami Hiramatsu @ 2025-11-21 15:22 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: linux-kernel, linux-trace-kernel, Masami Hiramatsu, Mark Rutland,
	Mathieu Desnoyers, Andrew Morton, Tom Zanussi
In-Reply-To: <20251120205710.314839538@kernel.org>

On Thu, 20 Nov 2025 15:56:03 -0500
Steven Rostedt <rostedt@kernel.org> wrote:

> From: Steven Rostedt <rostedt@goodmis.org>
> 
> The function trigger_process_regex() is called by a few functions, where
> only one calls strim() on the buffer passed to it. That leaves the other
> functions not trimming the end of the buffer passed in and making it a
> little inconsistent.
> 
> Remove the strim() from event_trigger_regex_write() and have
> trigger_process_regex() use strim() instead of skip_spaces(). The buff
> variable is not passed in as const, so it can be modified.
> 

Looks good to me.

Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>

Thanks,

> Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
> ---
>  kernel/trace/trace_events_trigger.c | 5 ++---
>  1 file changed, 2 insertions(+), 3 deletions(-)
> 
> diff --git a/kernel/trace/trace_events_trigger.c b/kernel/trace/trace_events_trigger.c
> index 16e3449f3cfe..1dfe69146a81 100644
> --- a/kernel/trace/trace_events_trigger.c
> +++ b/kernel/trace/trace_events_trigger.c
> @@ -309,7 +309,8 @@ int trigger_process_regex(struct trace_event_file *file, char *buff)
>  	char *command, *next;
>  	struct event_command *p;
>  
> -	next = buff = skip_spaces(buff);
> +	next = buff = strim(buff);
> +
>  	command = strsep(&next, ": \t");
>  	if (next) {
>  		next = skip_spaces(next);
> @@ -346,8 +347,6 @@ static ssize_t event_trigger_regex_write(struct file *file,
>  	if (IS_ERR(buf))
>  		return PTR_ERR(buf);
>  
> -	strim(buf);
> -
>  	guard(mutex)(&event_mutex);
>  
>  	event_file = event_file_file(file);
> -- 
> 2.51.0
> 
> 


-- 
Masami Hiramatsu (Google) <mhiramat@kernel.org>

^ permalink raw reply

* Re: [PATCH 2/3] tracing: Add bulk garbage collection of freeing event_trigger_data
From: Masami Hiramatsu @ 2025-11-21 15:12 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: linux-kernel, linux-trace-kernel, Masami Hiramatsu, Mark Rutland,
	Mathieu Desnoyers, Andrew Morton, Tom Zanussi
In-Reply-To: <20251120205710.151041470@kernel.org>

On Thu, 20 Nov 2025 15:56:02 -0500
Steven Rostedt <rostedt@kernel.org> wrote:

> From: Steven Rostedt <rostedt@goodmis.org>
> 
> The event trigger data requires a full tracepoint_synchronize_unregister()
> call before freeing. That call can take 100s of milliseconds to complete.
> In order to allow for bulk freeing of the trigger data, it can not call
> the tracepoint_synchronize_unregister() for every individual trigger data
> being free.
> 
> Create a kthread that gets created the first time a trigger data is freed,
> and have it use the lockless llist to get the list of data to free, run
> the tracepoint_synchronize_unregister() then free everything in the list.
> 
> By freeing hundreds of event_trigger_data elements together, it only
> requires two runs of the synchronization function, and not hundreds of
> runs. This speeds up the operation by orders of magnitude (milliseconds
> instead of several seconds).
> 

I have some nitpicks, but basically looks good to me.

Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>

> Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
> ---
>  kernel/trace/trace.h                |  1 +
>  kernel/trace/trace_events_trigger.c | 56 +++++++++++++++++++++++++++--
>  2 files changed, 54 insertions(+), 3 deletions(-)
> 
> diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
> index 5863800b1ab3..fd5a6daa6c25 100644
> --- a/kernel/trace/trace.h
> +++ b/kernel/trace/trace.h
> @@ -1808,6 +1808,7 @@ struct event_trigger_data {
>  	char				*name;
>  	struct list_head		named_list;
>  	struct event_trigger_data	*named_data;
> +	struct llist_node		llist;
>  };
>  
>  /* Avoid typos */
> diff --git a/kernel/trace/trace_events_trigger.c b/kernel/trace/trace_events_trigger.c
> index e5dcfcbb2cd5..16e3449f3cfe 100644
> --- a/kernel/trace/trace_events_trigger.c
> +++ b/kernel/trace/trace_events_trigger.c
> @@ -6,26 +6,76 @@
>   */
>  
>  #include <linux/security.h>
> +#include <linux/kthread.h>
>  #include <linux/module.h>
>  #include <linux/ctype.h>
>  #include <linux/mutex.h>
>  #include <linux/slab.h>
>  #include <linux/rculist.h>
> +#include <linux/llist.h>

nit: Shouldn't we include this in "trace.h" too, because llist_node is used?

>  
>  #include "trace.h"
>  
>  static LIST_HEAD(trigger_commands);
>  static DEFINE_MUTEX(trigger_cmd_mutex);
>  
> +static struct task_struct *trigger_kthread;
> +static struct llist_head trigger_data_free_list;
> +static DEFINE_MUTEX(trigger_data_kthread_mutex);
> +
> +/* Bulk garbage collection of event_trigger_data elements */
> +static int trigger_kthread_fn(void *ignore)
> +{
> +	struct event_trigger_data *data, *tmp;
> +	struct llist_node *llnodes;
> +
> +	/* Once this task starts, it lives forever */
> +	for (;;) {
> +		set_current_state(TASK_INTERRUPTIBLE);
> +		if (llist_empty(&trigger_data_free_list))
> +			schedule();
> +
> +		__set_current_state(TASK_RUNNING);
> +
> +		llnodes = llist_del_all(&trigger_data_free_list);
> +
> +		/* make sure current triggers exit before free */
> +		tracepoint_synchronize_unregister();
> +
> +		llist_for_each_entry_safe(data, tmp, llnodes, llist)
> +			kfree(data);
> +	}
> +
> +	return 0;
> +}
> +
>  void trigger_data_free(struct event_trigger_data *data)
>  {
>  	if (data->cmd_ops->set_filter)
>  		data->cmd_ops->set_filter(NULL, data, NULL);
>  
> -	/* make sure current triggers exit before free */
> -	tracepoint_synchronize_unregister();
> +	if (unlikely(!trigger_kthread)) {
> +		guard(mutex)(&trigger_data_kthread_mutex);
> +		/* Check again after taking mutex */
> +		if (!trigger_kthread) {
> +			struct task_struct *kthread;
> +
> +			kthread = kthread_create(trigger_kthread_fn, NULL,
> +						 "trigger_data_free");
> +			if (!IS_ERR(kthread))
> +				WRITE_ONCE(trigger_kthread, kthread);
> +		}
> +	}
> +

Hmm,
	/* This continues above error case, but we should do it without lock. */
?

> +	if (!trigger_kthread) {
> +		/* Do it the slow way */
> +		tracepoint_synchronize_unregister();
> +		kfree(data);
> +		return;
> +	}
>  
> -	kfree(data);
> +	llist_add(&data->llist, &trigger_data_free_list);
> +	wake_up_process(trigger_kthread);
>  }
>  
>  static inline void data_ops_trigger(struct event_trigger_data *data,
> -- 
> 2.51.0
> 
> 


-- 
Masami Hiramatsu (Google) <mhiramat@kernel.org>

^ permalink raw reply

* Re: [PATCHv3 bpf-next 5/8] ftrace: Add update_ftrace_direct_mod function
From: Jiri Olsa @ 2025-11-21 13:53 UTC (permalink / raw)
  To: bot+bpf-ci
  Cc: rostedt, revest, mark.rutland, bpf, linux-kernel,
	linux-trace-kernel, linux-arm-kernel, ast, daniel, andrii,
	menglong8.dong, song, martin.lau, eddyz87, yonghong.song, clm,
	ihor.solodrai
In-Reply-To: <a302c70bc1914835ea69c8b30105741b1d1d06d549ef95b9650d0827e0ca276a@mail.kernel.org>

On Thu, Nov 20, 2025 at 10:23:47PM +0000, bot+bpf-ci@kernel.org wrote:
> > diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
> > index c571deeff..4e2c0ed76 100644
> > --- a/include/linux/ftrace.h
> > +++ b/include/linux/ftrace.h
> 
> [ ... ]
> 
> > diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
> > index cc730a8fd..5243aefb6 100644
> > --- a/kernel/trace/ftrace.c
> > +++ b/kernel/trace/ftrace.c
> 
> [ ... ]
> 
> > @@ -6486,6 +6486,74 @@ int update_ftrace_direct_del(struct ftrace_ops *ops, struct ftrace_hash *hash)
> >  	return err;
> >  }
> >
> > +int update_ftrace_direct_mod(struct ftrace_ops *ops, struct ftrace_hash *hash, bool do_direct_lock)
> > +{
> > +	struct ftrace_hash *orig_hash = ops->func_hash->filter_hash;
>                                              ^^^^^^^^^^^^^^^^
> 
> Can this crash if ops->func_hash is NULL?  In update_ftrace_direct_add()
> and update_ftrace_direct_del(), there's a defensive check:
> 
>     old_filter_hash = ops->func_hash ? ops->func_hash->filter_hash : NULL;
> 
> But update_ftrace_direct_mod() dereferences ops->func_hash before any
> validation checks occur. The check_direct_multi(ops) validation happens
> later, but the dereference occurs first at function entry.

update_ftrace_direct_add is called before update_ftrace_direct_mod which
ensures the existence of the filter_hash, but same as for the update_ftrace_direct_del
case in the other reply, it's probably better to add the check for future

thanks,
jirka


> 
> > +	struct ftrace_func_entry *entry, *tmp;
> > +	static struct ftrace_ops tmp_ops = {
> > +		.func		= ftrace_stub,
> > +		.flags		= FTRACE_OPS_FL_STUB,
> > +	};
> > +	unsigned long size, i;
> > +	int err;
> > +
> > +	if (!hash_count(hash))
> > +		return -EINVAL;
> > +	if (check_direct_multi(ops))
> > +		return -EINVAL;
> 
> [ ... ]
> 
> 
> ---
> AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
> See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
> 
> CI run summary: https://github.com/kernel-patches/bpf/actions/runs/19552032346


^ permalink raw reply

* Re: [PATCHv3 bpf-next 4/8] ftrace: Add update_ftrace_direct_del function
From: Jiri Olsa @ 2025-11-21 13:52 UTC (permalink / raw)
  To: bot+bpf-ci
  Cc: rostedt, revest, mark.rutland, bpf, linux-kernel,
	linux-trace-kernel, linux-arm-kernel, ast, daniel, andrii,
	menglong8.dong, song, martin.lau, eddyz87, yonghong.song, clm,
	ihor.solodrai
In-Reply-To: <35e436ca1a638c9e30456c2a3645c23a20b2483160e3bb34b7c73fe42776f4df@mail.kernel.org>

On Thu, Nov 20, 2025 at 10:23:46PM +0000, bot+bpf-ci@kernel.org wrote:
> > diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
> > index 9cf4cd56d..c571deeff 100644
> > --- a/include/linux/ftrace.h
> > +++ b/include/linux/ftrace.h
> > @@ -551,6 +551,7 @@ int modify_ftrace_direct(struct ftrace_ops *ops, unsigned long addr);
> >  int modify_ftrace_direct_nolock(struct ftrace_ops *ops, unsigned long addr);
> >
> >  int update_ftrace_direct_add(struct ftrace_ops *ops, struct ftrace_hash *hash);
> > +int update_ftrace_direct_del(struct ftrace_ops *ops, struct ftrace_hash *hash);
> >
> >  void ftrace_stub_direct_tramp(void);
> >
> > @@ -583,6 +584,11 @@ static inline int update_ftrace_direct_add(struct ftrace_ops *ops, struct ftrace
> >  	return -ENODEV;
> >  }
> >
> > +static inline int update_ftrace_direct_del(struct ftrace_ops *ops, struct ftrace_hash *hash)
> > +{
> > +	return -ENODEV;
> > +}
> > +
> 
> [ ... ]
> 
> > diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
> > index 850ff55ff..cc730a8fd 100644
> > --- a/kernel/trace/ftrace.c
> > +++ b/kernel/trace/ftrace.c
> 
> [ ... ]
> 
> > +/**
> > + * hash_sub - substracts @b from @a and returns the result
> > + * @a: struct ftrace_hash object
> > + * @b: struct ftrace_hash object
> > + *
> > + * Returns struct ftrace_hash object on success, NULL on error.
> > + */
> > +static struct ftrace_hash *hash_sub(struct ftrace_hash *a, struct ftrace_hash *b)
> > +{
> > +	struct ftrace_func_entry *entry, *del;
> > +	struct ftrace_hash *sub;
> > +	int size, i;
> > +
> > +	sub = alloc_and_copy_ftrace_hash(a->size_bits, a);
>                                            ^^^^^^^^^^^^
> 
> Can hash_sub() handle a NULL hash pointer in parameter a?  I notice the
> parallel function hash_add() safely handles NULL via hash_count() and
> alloc_and_copy_ftrace_hash() which checks ftrace_hash_empty().
> 
> However, hash_sub() directly dereferences a->size_bits before passing a
> to alloc_and_copy_ftrace_hash().  This will crash if a is NULL.
> 
> This matters because update_ftrace_direct_del() calls hash_sub() with
> old_filter_hash which can be NULL:
> 
>     old_filter_hash = ops->func_hash ? ops->func_hash->filter_hash : NULL;
>     ...
>     new_filter_hash = hash_sub(old_filter_hash, hash);
> 
> The existing update_ftrace_direct_add() has the same defensive check and
> passes the potentially-NULL old_filter_hash to hash_add(), which handles
> it correctly.

so we never call update_ftrace_direct_del without having
update_ftrace_direct_add called, which ensures the existence of filter_hash,
but it's probably good idea to do explicit check for future

thanks,
jirka


> 
> > +	if (!sub)
> > +		goto error;
> > +
> > +	size = 1 << b->size_bits;
> > +	for (i = 0; i < size; i++) {
> > +		hlist_for_each_entry(entry, &b->buckets[i], hlist) {
> > +			del = __ftrace_lookup_ip(sub, entry->ip);
> > +			if (WARN_ON_ONCE(!del))
> > +				goto error;
> > +			remove_hash_entry(sub, del);
> > +			kfree(del);
> > +		}
> > +	}
> > +	return sub;
> > +
> > + error:
> > +	free_ftrace_hash(sub);
> > +	return NULL;
> > +}
> > +
> > +int update_ftrace_direct_del(struct ftrace_ops *ops, struct ftrace_hash *hash)
> > +{
> 
> [ ... ]
> 
> 
> ---
> AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
> See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
> 
> CI run summary: https://github.com/kernel-patches/bpf/actions/runs/19552032346


^ permalink raw reply

* [GIT PULL v2] RTLA updates for v6.19
From: Tomas Glozar @ 2025-11-21 12:46 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Costa Shulyupin, Crystal Wood, Ivan Pravdin, John Kacur, LKML,
	Linux Trace Kernel, Tomas Glozar

Hi Steven,

Please use this amended tag for the merge window in place of the old one. The
diff between rtla-v6.19-v2 and rtla-v6.19 is empty, it is just the tweak of the
commit messages and a note about a merge conflict.

Thanks,
Tomas

The following changes since commit 0d5077c73aceb51ef10d096160dd62a11db2f3e4:

  MAINTAINERS: Add Tomas Glozar as a maintainer to RTLA tool (2025-11-14 12:24:41 -0500)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/tglozar/linux.git/ tags/rtla-v6.19-v2

for you to fetch changes up to 3138df6f0cd04a75f8efa5b5270ba56d00a84ae6:

  rtla/timerlat: Exit top main loop on any non-zero wait_retval (2025-11-21 10:30:27 +0100)

----------------------------------------------------------------
RTLA patches for v6.19

Fixes and minor cleanups for RTLA, targetting v6.19 via
linux-trace tools/for-next:

- Add for_each_monitored_cpu() helper

  In multiple places, RTLA tools iterate over the list of CPUs running
  tracer threads.

  Use single helper instead of repeating the for/if combination.

- Remove unused variable option_index in argument parsing

  RTLA tools use getopt_long() for argument parsing. For its last
  argument, an unused variable "option_index" is passed.

  Remove the variable and pass NULL to getopt_long() to shorten
  the naturally long parsing functions, and make them more readable.

- Fix unassigned nr_cpus after code consolidation

  In recent code consolidation, timerlat tool cleanup, previously
  implemented separately for each tool, was moved to a common function
  timerlat_free().

  The cleanup relies on nr_cpus being set. This was not done in the new
  function, leaving the variable uninitialized.

  Initialize the variable properly, and remove silencing of compiler
  warning for uninitialized variables.

- Stop tracing on user latency in BPF mode

  Despite the name, rtla-timerlat's -T/--thread option sets timerlat's
  stop_tracing_total_us option, which also stops tracing on
  return-from-user latency, not only on thread latency.

  Implement the same behavior also in BPF sample collection stop tracing
  handler to avoid a discrepancy and restore correspondence of behavior
  with the equivalent option of cyclictest.

- Fix threshold actions always triggering

  A bug in threshold action logic caused the action to execute even
  if tracing did not stop because of threshold.

  Fix the logic to stop correctly.

- Fix few minor issues in tests

  Extend tests that were shown to need it to 5s, fix osnoise test
  calling timerlat by mistake, and use new, more reliable output
  checking in timerlat's "top stop at failed action" test.

- Do not print usage on argument parsing error

  RTLA prints the entire usage message on encountering errors in
  argument parsing, like a malformed CPU list.

  The usage message has gotten too long. Instead of printing it,
  use newly added fatal() helper function to simply exit with
  the error message, excluding the usage.

- Fix unintuitive -C/--cgroup interface

  "-C cgroup" and "--cgroup cgroup" are invalid syntax, despite that
  being a common way to specify an option with argument. Moreover,
  using them fails silently and no cgroup is set.

  Create new helper function to unify the handling of all such options
  and allow all of:

  -Xsomething
  -X=something
  -X something

  as well as the equivalent for the long option.

- Fix -a overriding -t argument filename

  Fix a bug where -a following -t custom_file.txt overrides the custom
  filename with the default timerlat_trace.txt.

- Stop tracing correctly on multiple events at once

  In some race scenarios, RTLA BPF sample collection might send multiple
  stop tracing events via the BPF ringbuffer at once.

  Compare the number of events for != 0 instead of == 1 to cover for
  this scenario and stop tracing properly.

The tag was tested on both a non-RT-tuned and an RT-tuned machine, and
no issues were found besides known cases of the flakiness of tests for
stack dump and auto-analysis, which rely on correct order of events.

The patchset mostly consists of fixes originally targetting one of
the v6.18-rcs rather than linux-next and the v6.19 merge window; one
of them is even Cc: stable. The delay was caused by maintainership
handover of RTLA.

CONFLICTS: The patch "rtla: Fix -C/--cgroup interface" has a minor
rename and context conflict with patches 96b546c241b1
("Documentation/rtla: rename common_xxx.rst files to common_xxx.txt")
and 198fcc7cb832 ("Documentation/rtla: Mention default priority"),
which were picked earlier by Jonathan Corbet's linux-docs tree.

v2:
- Fix Fixes: tags containing 11 characters instead of 12 for commit
"rtla/tests: Fix osnoise test calling timerlat" and commit
"rtla/tests: Extend action tests to 5s".

Signed-off-by: Tomas Glozar <tglozar@redhat.com>

----------------------------------------------------------------
Costa Shulyupin (8):
      tools/rtla: Add for_each_monitored_cpu() helper
      tools/rtla: Remove unused optional option_index
      tools/rtla: Fix unassigned nr_cpus
      tools/rtla: Add fatal() and replace error handling pattern
      tools/rtla: Replace timerlat_top_usage("...") with fatal("...")
      tools/rtla: Replace timerlat_hist_usage("...") with fatal("...")
      tools/rtla: Replace osnoise_top_usage("...") with fatal("...")
      tools/rtla: Replace osnoise_hist_usage("...") with fatal("...")

Crystal Wood (2):
      rtla/tests: Don't rely on matching ^1ALL
      rtla/timerlat: Exit top main loop on any non-zero wait_retval

Ivan Pravdin (2):
      rtla: Fix -C/--cgroup interface
      rtla: Fix -a overriding -t argument

Tomas Glozar (4):
      rtla/timerlat_bpf: Stop tracing on user latency
      tools/rtla: Fix --on-threshold always triggering
      rtla/tests: Extend action tests to 5s
      rtla/tests: Fix osnoise test calling timerlat

 Documentation/tools/rtla/common_options.rst |   2 +-
 tools/tracing/rtla/Makefile.rtla            |   2 +-
 tools/tracing/rtla/src/common.c             |  24 +++--
 tools/tracing/rtla/src/common.h             |   4 +
 tools/tracing/rtla/src/osnoise_hist.c       | 136 +++++++++----------------
 tools/tracing/rtla/src/osnoise_top.c        | 106 +++++++-------------
 tools/tracing/rtla/src/timerlat.bpf.c       |   3 +
 tools/tracing/rtla/src/timerlat.c           |  12 +--
 tools/tracing/rtla/src/timerlat_hist.c      | 148 +++++++++-------------------
 tools/tracing/rtla/src/timerlat_top.c       | 116 ++++++++--------------
 tools/tracing/rtla/src/timerlat_u.c         |  12 +--
 tools/tracing/rtla/src/utils.c              |  41 ++++++++
 tools/tracing/rtla/src/utils.h              |   2 +
 tools/tracing/rtla/tests/osnoise.t          |   6 +-
 tools/tracing/rtla/tests/timerlat.t         |   6 +-
 15 files changed, 247 insertions(+), 373 deletions(-)


^ permalink raw reply

* [syzbot] Monthly trace report (Nov 2025)
From: syzbot @ 2025-11-21 12:34 UTC (permalink / raw)
  To: linux-kernel, linux-trace-kernel, mhiramat, syzkaller-bugs

Hello trace maintainers/developers,

This is a 31-day syzbot report for the trace subsystem.
All related reports/information can be found at:
https://syzkaller.appspot.com/upstream/s/trace

During the period, 1 new issues were detected and 0 were fixed.
In total, 15 issues are still open and 59 have already been fixed.

Some of the still happening issues:

Ref Crashes Repro Title
<1> 773     Yes   INFO: task hung in exit_mm (5)
                  https://syzkaller.appspot.com/bug?extid=1c6607097b258f18065c
<2> 87      Yes   WARNING in blk_register_tracepoints
                  https://syzkaller.appspot.com/bug?extid=c54ded83396afee31eb1
<3> 82      Yes   WARNING in tracepoint_probe_unregister (3)
                  https://syzkaller.appspot.com/bug?extid=a1d25e53cd4a10f7f2d3
<4> 60      Yes   INFO: task hung in blk_trace_ioctl (4)
                  https://syzkaller.appspot.com/bug?extid=ed812ed461471ab17a0c
<5> 58      Yes   INFO: task hung in blk_trace_remove (2)
                  https://syzkaller.appspot.com/bug?extid=2373f6be3e6de4f92562
<6> 30      No    INFO: task hung in blk_trace_startstop
                  https://syzkaller.appspot.com/bug?extid=774863666ef5b025c9d0
<7> 19      Yes   WARNING in get_probe_ref
                  https://syzkaller.appspot.com/bug?extid=8672dcb9d10011c0a160

---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.

To disable reminders for individual bugs, reply with the following command:
#syz set <Ref> no-reminders

To change bug's subsystems, reply with:
#syz set <Ref> subsystems: new-subsystem

You may send multiple commands in a single email message.

^ permalink raw reply

* Re: [RFC PATCH v7 29/31] x86/mm/pti: Implement a TLB flush immediately after a switch to kernel CR3
From: Valentin Schneider @ 2025-11-21 10:12 UTC (permalink / raw)
  To: Andy Lutomirski, Linux Kernel Mailing List, linux-mm, rcu,
	the arch/x86 maintainers, linux-arm-kernel, loongarch,
	linux-riscv, linux-arch, linux-trace-kernel
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
	H. Peter Anvin, Peter Zijlstra (Intel), Arnaldo Carvalho de Melo,
	Josh Poimboeuf, Paolo Bonzini, Arnd Bergmann, Frederic Weisbecker,
	Paul E. McKenney, Jason Baron, Steven Rostedt, Ard Biesheuvel,
	Sami Tolvanen, David S. Miller, Neeraj Upadhyay, Joel Fernandes,
	Josh Triplett, Boqun Feng, Uladzislau Rezki, Mathieu Desnoyers,
	Mel Gorman, Andrew Morton, Masahiro Yamada, Han Shen,
	Rik van Riel, Jann Horn, Dan Carpenter, Oleg Nesterov, Juri Lelli,
	Clark Williams, Yair Podemsky, Marcelo Tosatti, Daniel Wagner,
	Petr Tesarik, Shrikanth Hegde
In-Reply-To: <91702ceb-afba-450e-819b-52d482d7bd11@app.fastmail.com>

On 19/11/25 09:31, Andy Lutomirski wrote:
> Let's consider what we're worried about:
>
> 1. Architectural access to a kernel virtual address that has been unmapped, in asm or early C.  If it hasn't been remapped, then we oops anyway.  If it has, then that means we're accessing a pointer where either the pointer has changed or the pointee has been remapped while we're in user mode, and that's a very strange thing to do for anything that the asm points to or that early C points to, unless RCU is involved.  But RCU is already disallowed in the entry paths that might be in extended quiescent states, so I think this is mostly a nonissue.
>
> 2. Non-speculative access via GDT access, etc.  We can't control this at all, but we're not avoid to move the GDT, IDT, LDT etc of a running task while that task is in user mode.  We do move the LDT, but that's quite thoroughly synchronized via IPI.  (Should probably be double checked.  I wrote that code, but that doesn't mean I remember it exactly.)
>
> 3. Speculative TLB fills.  We can't control this at all.  We have had actual machine checks, on AMD IIRC, due to messing this up.  This is why we can't defer a flush after freeing a page table.
>
> 4. Speculative or other nonarchitectural loads.  One would hope that these are not dangerous.  For example, an early version of TDX would machine check if we did a speculative load from TDX memory, but that was fixed.  I don't see why this would be materially different between actual userspace execution (without LASS, anyway), kernel asm, and kernel C.
>
> 5. Writes to page table dirty bits.  I don't think we use these.
>
> In any case, the current implementation in your series is really, really,
> utterly horrifically slow.

Quite so :-)

> It's probably fine for a task that genuinely sits in usermode forever,
> but I don't think it's likely to be something that we'd be willing to
> enable for normal kernels and normal tasks.  And it would be really nice
> for the don't-interrupt-user-code still to move toward being always
> available rather than further from it.
>

Well following Frederic's suggestion of using the "is NOHZ_FULL actually in
use" static key in the ASM bits, none of the ugly bits get involved unless
you do have 'nohz_full=' on the cmdline - not perfect, but it's something.

RHEL kernels ship with NO_HZ_FULL=y [1], so we do care about that not impacting
performance too much if it's just compiled-in and not actually used.

[1]: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/blob/main/redhat/configs/common/generic/CONFIG_NO_HZ_FULL
>
> I admit that I'm kind of with dhansen: Zen 3+ can use INVLPGB and doesn't
> need any of this.  Some Intel CPUs support RAR and will eventually be
> able to use RAR, possibly even for sync_core().

Yeah that INVLPGB thing looks really nice, and AFAICT arm64 is similarly
covered with TLBI VMALLE1IS.

My goal here is to poke around and find out what's the minimal amount of
ugly we can get away with to suppress those IPIs on existing fleets, but
there's still too much ugly :/


^ permalink raw reply

* Re: [PATCH 1/3] tracing: Remove unneeded event_mutex lock in event_trigger_regex_release()
From: Masami Hiramatsu @ 2025-11-21  8:47 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: linux-kernel, linux-trace-kernel, Masami Hiramatsu, Mark Rutland,
	Mathieu Desnoyers, Andrew Morton, Tom Zanussi
In-Reply-To: <20251120205709.984522508@kernel.org>

On Thu, 20 Nov 2025 15:56:01 -0500
Steven Rostedt <rostedt@kernel.org> wrote:

> From: Steven Rostedt <rostedt@goodmis.org>
> 
> In event_trigger_regex_release(), the only code is:
> 
> 	mutex_lock(&event_mutex);
> 	if (file->f_mode & FMODE_READ)
> 		seq_release(inode, file);
> 	mutex_unlock(&event_mutex);
> 
> 	return 0;
> 
> There's nothing special about the file->f_mode or the seq_release() that
> requires any locking. Remove the unnecessary locks.
> 

Looks good to me.

Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>

> Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
> ---
>  kernel/trace/trace_events_trigger.c | 4 ----
>  1 file changed, 4 deletions(-)
> 
> diff --git a/kernel/trace/trace_events_trigger.c b/kernel/trace/trace_events_trigger.c
> index 7795af600466..e5dcfcbb2cd5 100644
> --- a/kernel/trace/trace_events_trigger.c
> +++ b/kernel/trace/trace_events_trigger.c
> @@ -314,13 +314,9 @@ static ssize_t event_trigger_regex_write(struct file *file,
>  
>  static int event_trigger_regex_release(struct inode *inode, struct file *file)
>  {
> -	mutex_lock(&event_mutex);
> -
>  	if (file->f_mode & FMODE_READ)
>  		seq_release(inode, file);
>  
> -	mutex_unlock(&event_mutex);
> -
>  	return 0;
>  }
>  
> -- 
> 2.51.0
> 
> 


-- 
Masami Hiramatsu (Google) <mhiramat@kernel.org>

^ permalink raw reply

* Re: [PATCH v3] mm/memory-failure: remove the selection of RAS
From: Miaohe Lin @ 2025-11-21  7:39 UTC (permalink / raw)
  To: Xie Yuanbin
  Cc: linux-kernel, linux-edac, linux-mm, linux-trace-kernel, will,
	liaohua4, lilinjie8, david, tony.luck, bp, nao.horiguchi, rostedt,
	mhiramat, mathieu.desnoyers, akpm, david, lorenzo.stoakes,
	Liam.Howlett, vbabka, rppt, surenb, mhocko
In-Reply-To: <20251119095943.67125-1-xieyuanbin1@huawei.com>

On 2025/11/19 17:59, Xie Yuanbin wrote:
> The commit 97f0b13452198290799f ("tracing: add trace event for
> memory-failure") introduces the selection of RAS in memory-failure.
> This commit is just a tracing feature; in reality, there is no dependency
> between memory-failure and RAS. RAS increases the size of the bzImage
> image by 8k, which is very valuable for embedded devices.
> 
> Move the memory-failure traceing code from ras_event.h to
> memory-failure.h and remove the selection of RAS.
> 
> v2->v3: https://lore.kernel.org/20251104072306.100738-3-xieyuanbin1@huawei.com
>   - Change define TRACE_SYSTEM from ras to memory_failure
>   - Add include/trace/events/memory-failure.h to
>     "HWPOISON MEMORY FAILURE HANDLING" section in MAINTAINERS
>   - Rebase to latest linux-next source
> 
> v1->v2: https://lore.kernel.org/20251103033536.52234-2-xieyuanbin1@huawei.com
>   - Move the memory-failure traceing code from ras_event.h to
>     memory-failure.h
> 
> Signed-off-by: Xie Yuanbin <xieyuanbin1@huawei.com>
> Cc: David Hildenbrand (Red Hat) <david@kernel.org>
> Cc: Borislav Petkov <bp@alien8.de>
> Cc: Miaohe Lin <linmiaohe@huawei.com>

LGTM. With David's comment addressed,

Acked-by: Miaohe Lin <linmiaohe@huawei.com>

Thanks.
.


^ permalink raw reply

* [RESEND PATCH V4] sched: psi: Add psi events trace point
From: Xuewen Yan @ 2025-11-21  7:32 UTC (permalink / raw)
  To: peterz, surenb, rostedt, mhiramat, mathieu.desnoyers, hannes,
	vincent.guittot
  Cc: mingo, juri.lelli, dietmar.eggemann, bsegall, mgorman,
	linux-kernel, linux-trace-kernel, yuming.han, xuewen.yan94,
	ke.wang, jstultz

Add trace point to psi triggers. This is useful to
observe the psi events in the kernel space.

One use of this is to monitor memory pressure.
When the pressure is too high, we can kill the process
in the kernel space to prevent OOM.

Signed-off-by: Xuewen Yan <xuewen.yan@unisoc.com>
Acked-by: Suren Baghdasaryan <surenb@google.com>
---
V4:
-generate the event only after cmpxchg() passes the check
---
V3:
-export it in the tracefs;
---
v2:
-fix compilation error;
-export the tp;
-add more commit message;
---
 include/trace/events/sched.h | 27 +++++++++++++++++++++++++++
 kernel/sched/psi.c           |  5 +++++
 2 files changed, 32 insertions(+)

diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h
index 7b2645b50e78..db8b8f25466e 100644
--- a/include/trace/events/sched.h
+++ b/include/trace/events/sched.h
@@ -826,6 +826,33 @@ TRACE_EVENT(sched_wake_idle_without_ipi,
 	TP_printk("cpu=%d", __entry->cpu)
 );
 
+#ifdef CONFIG_PSI
+TRACE_EVENT(psi_event,
+
+	TP_PROTO(int aggregator, int state, u64 threshold, u64 win_size),
+
+	TP_ARGS(aggregator, state, threshold, win_size),
+
+	TP_STRUCT__entry(
+		__field(int,	aggregator)
+		__field(int,	state)
+		__field(u64,	threshold)
+		__field(u64,	win_size)
+	),
+
+	TP_fast_assign(
+		__entry->aggregator	= aggregator;
+		__entry->state		= state;
+		__entry->threshold	= threshold;
+		__entry->win_size	= win_size;
+	),
+
+	TP_printk("aggregator=%d state=%d threshold=%llu window_size=%llu",
+		__entry->aggregator, __entry->state, __entry->threshold,
+		__entry->win_size)
+);
+#endif /* CONFIG_PSI */
+
 /*
  * Following tracepoints are not exported in tracefs and provide hooking
  * mechanisms only for testing and debugging purposes.
diff --git a/kernel/sched/psi.c b/kernel/sched/psi.c
index 59fdb7ebbf22..e8a7fd04ba9f 100644
--- a/kernel/sched/psi.c
+++ b/kernel/sched/psi.c
@@ -141,6 +141,8 @@
 #include <linux/psi.h>
 #include "sched.h"
 
+EXPORT_TRACEPOINT_SYMBOL_GPL(psi_event);
+
 static int psi_bug __read_mostly;
 
 DEFINE_STATIC_KEY_FALSE(psi_disabled);
@@ -515,6 +517,9 @@ static void update_triggers(struct psi_group *group, u64 now,
 				kernfs_notify(t->of->kn);
 			else
 				wake_up_interruptible(&t->event_wait);
+
+			trace_psi_event(aggregator, t->state, t->threshold,
+					t->win.size);
 		}
 		t->last_event_time = now;
 		/* Reset threshold breach flag once event got generated */
-- 
2.25.1


^ permalink raw reply related


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