Linux Trace Kernel
 help / color / mirror / Atom feed
* Re: [PATCH v3 RESEND] function_graph: Enable funcgraph-args and funcgraph-retaddr to work simultaneously
From: Donglin Peng @ 2025-11-13  3:01 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Masami Hiramatsu, linux-trace-kernel, linux-kernel, Donglin Peng,
	Sven Schnelle
In-Reply-To: <CAErzpmsn-uys3VdchF_CKBPUQT+328wtaKnbufoDi-o9x7eHaA@mail.gmail.com>

On Thu, Nov 13, 2025 at 10:38 AM Donglin Peng <dolinux.peng@gmail.com> wrote:
>
> On Thu, Nov 13, 2025 at 10:02 AM Steven Rostedt <rostedt@goodmis.org> wrote:
> >
> > On Thu, 13 Nov 2025 09:48:52 +0800
> > Donglin Peng <dolinux.peng@gmail.com> wrote:
> >
> > > I noticed that when funcgraph-args is enabled, it registers
> > > trace_graph_entry_args
> > > to replace trace_graph_entry. The only difference is whether a valid
> > > fregs pointer
> > > is passed.
> > >
> > > To reduce overhead, I propose consolidating the two entry functions. We could
> > > maintain only trace_graph_entry and pass the fregs parameter to graph_entry.
> > > Within __graph_entry, we can then conditionally record arguments based on
> > > 'TRACE_GRAPH_ARGS && !!fregs'.
> >
> > What overhead are you reducing?  Why add a branch statement in a critical path?
>
> Thanks. During testing, I found that enabling funcgraph-args incurs significant
> overhead (344ms) compared to other trace options (near-zero).
>
> # time echo 1 > options/funcgraph-retaddr
>
> real    0m0.000s
> user    0m0.000s
> sys     0m0.000s
>
> # time  echo 1 > options/funcgraph-args
>
> real    0m0.344s
> user    0m0.000s
> sys     0m0.344s
>
> So I thought it may need to be optimized.
>
> >
> > The graph_entry() should not be looking at the flags argument. It's called
> > by *every function*. Also note, I recently fixed the flags to be per
> > instance and not global. Which means testing the flags would require
> > indirection lookups.
>
> Thanks, I agree and it indeed introduces extra branch instruction and
> may introduce more overhead when using indirection lookups.

Is it necessary to do the same thing for funcgraph-retaddr considering
that it checks the global tracer_flags in the graph_entry?

>
> >
> > -- Steve

^ permalink raw reply

* Re: [PATCH v2 5/7] kallsyms/bpf: Rename __bpf_address_lookup() to bpf_address_lookup()
From: Alexei Starovoitov @ 2025-11-13  2:50 UTC (permalink / raw)
  To: Petr Mladek
  Cc: Petr Pavlu, Steven Rostedt, Alexei Starovoitov, Andrew Morton,
	Kees Cook, Aaron Tomlin, Daniel Borkmann, John Fastabend,
	Masami Hiramatsu, Mark Rutland, Luis Chamberlain, Daniel Gomez,
	Sami Tolvanen, LKML, bpf, linux-modules, linux-trace-kernel
In-Reply-To: <20251112142003.182062-6-pmladek@suse.com>

On Wed, Nov 12, 2025 at 6:21 AM Petr Mladek <pmladek@suse.com> wrote:
>
> bpf_address_lookup() has been used only in kallsyms_lookup_buildid().
> It was supposed to set @modname and @modbuildid when the symbol was
> in a module.
>
> But it always just cleared @modname because BPF symbols were never in
> a module. And it did not clear @modbuildid because the pointer was
> not passed.
>
> The wrapper is not longer needed. Both @modname and @modbuildid

is no longer

> are newly always initialized to NULL in kallsyms_lookup_buildid().

are now?

> Remove the wrapper and rename __bpf_address_lookup() to
> bpf_address_lookup() because this variant is used everywhere.
>
> Fixes: 9294523e3768 ("module: add printk formats to add module build ID to stacktraces")
> Signed-off-by: Petr Mladek <pmladek@suse.com>

other than typos in the commit log it lgtm.

Acked-by: Alexei Starovoitov <ast@kernel.org>

^ permalink raw reply

* Re: [PATCH v3 RESEND] function_graph: Enable funcgraph-args and funcgraph-retaddr to work simultaneously
From: Donglin Peng @ 2025-11-13  2:38 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Masami Hiramatsu, linux-trace-kernel, linux-kernel, Donglin Peng,
	Sven Schnelle
In-Reply-To: <20251112210236.07deb6b2@gandalf.local.home>

On Thu, Nov 13, 2025 at 10:02 AM Steven Rostedt <rostedt@goodmis.org> wrote:
>
> On Thu, 13 Nov 2025 09:48:52 +0800
> Donglin Peng <dolinux.peng@gmail.com> wrote:
>
> > I noticed that when funcgraph-args is enabled, it registers
> > trace_graph_entry_args
> > to replace trace_graph_entry. The only difference is whether a valid
> > fregs pointer
> > is passed.
> >
> > To reduce overhead, I propose consolidating the two entry functions. We could
> > maintain only trace_graph_entry and pass the fregs parameter to graph_entry.
> > Within __graph_entry, we can then conditionally record arguments based on
> > 'TRACE_GRAPH_ARGS && !!fregs'.
>
> What overhead are you reducing?  Why add a branch statement in a critical path?

Thanks. During testing, I found that enabling funcgraph-args incurs significant
overhead (344ms) compared to other trace options (near-zero).

# time echo 1 > options/funcgraph-retaddr

real    0m0.000s
user    0m0.000s
sys     0m0.000s

# time  echo 1 > options/funcgraph-args

real    0m0.344s
user    0m0.000s
sys     0m0.344s

So I thought it may need to be optimized.

>
> The graph_entry() should not be looking at the flags argument. It's called
> by *every function*. Also note, I recently fixed the flags to be per
> instance and not global. Which means testing the flags would require
> indirection lookups.

Thanks, I agree and it indeed introduces extra branch instruction and
may introduce more overhead when using indirection lookups.

>
> -- Steve

^ permalink raw reply

* Re: [PATCH v3 RESEND] function_graph: Enable funcgraph-args and funcgraph-retaddr to work simultaneously
From: Steven Rostedt @ 2025-11-13  2:02 UTC (permalink / raw)
  To: Donglin Peng
  Cc: Masami Hiramatsu, linux-trace-kernel, linux-kernel, Donglin Peng,
	Sven Schnelle
In-Reply-To: <CAErzpmt8Dsq3f6ZUvtmc25hvy0NH6uRxBHPSxeZhkFfzkdJ04g@mail.gmail.com>

On Thu, 13 Nov 2025 09:48:52 +0800
Donglin Peng <dolinux.peng@gmail.com> wrote:

> I noticed that when funcgraph-args is enabled, it registers
> trace_graph_entry_args
> to replace trace_graph_entry. The only difference is whether a valid
> fregs pointer
> is passed.
> 
> To reduce overhead, I propose consolidating the two entry functions. We could
> maintain only trace_graph_entry and pass the fregs parameter to graph_entry.
> Within __graph_entry, we can then conditionally record arguments based on
> 'TRACE_GRAPH_ARGS && !!fregs'.

What overhead are you reducing?  Why add a branch statement in a critical path?

The graph_entry() should not be looking at the flags argument. It's called
by *every function*. Also note, I recently fixed the flags to be per
instance and not global. Which means testing the flags would require
indirection lookups.

-- Steve

^ permalink raw reply

* Re: [PATCH v3 RESEND] function_graph: Enable funcgraph-args and funcgraph-retaddr to work simultaneously
From: Donglin Peng @ 2025-11-13  1:48 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Masami Hiramatsu, linux-trace-kernel, linux-kernel, Donglin Peng,
	Sven Schnelle
In-Reply-To: <20251112103804.4a43591a@gandalf.local.home>

On Wed, Nov 12, 2025 at 11:37 PM Steven Rostedt <rostedt@goodmis.org> wrote:
>
> On Wed, 12 Nov 2025 17:00:10 +0800
> Donglin Peng <dolinux.peng@gmail.com> wrote:
>
> > I have a question regarding the behavior of the funcgraph-args option.
> >
> > Currently, when the funcgraph-args flag is set, the function arguments
> > are saved.
> > However, when the flag is cleared, the trace output still displays the function
> > arguments unconditionally.
>
> Yes. The flag affects the behavior of the recording and not the displaying
> of the arguments. There's no reason *not* to show them if they have already
> been recorded. Recording the arguments causes a noticeable overhead which
> is why it is optional.

Thank you for the clarification.

I noticed that when funcgraph-args is enabled, it registers
trace_graph_entry_args
to replace trace_graph_entry. The only difference is whether a valid
fregs pointer
is passed.

To reduce overhead, I propose consolidating the two entry functions. We could
maintain only trace_graph_entry and pass the fregs parameter to graph_entry.
Within __graph_entry, we can then conditionally record arguments based on
'TRACE_GRAPH_ARGS && !!fregs'.

Additionally, I've confirmed that trace_graph_entry is exclusively used by the
function_graph tracer. Other tracers like irqsoff and wakeup directly call
__trace_graph_entry with a NULL fregs pointer. Therefore, this consolidation
would not impact those tracers.

What are your thoughts on this approach?

Thanks,
Donglin


>
> >
> > I expected that the flag would control both saving and displaying the arguments.
> > But it seems that the current design only controls the saving. This
> > behavior seems
> > inconsistent.
>
> Not at all. The option is only for the recording. Otherwise, one might
> expect than they could do the recording and then after the fact enable
> "func-args" and expect to see them. That would be more inconsistent.
>
> >
> > I think we should add a check for the flag in the display part,
> > specifically before
> > calling print_function_args, to ensure that the arguments are only
> > displayed when
> > the flag is set.
> >
> > What are your thoughts?
>
> Big nope!
>
> The retaddr is different, as the information is somewhat redundant to the
> call chain and may cause more noise then needed.
>
> -- Steve

^ permalink raw reply

* Re: [RFC PATCH v1 03/37] KVM: Enumerate support for PRIVATE memory iff kvm_arch_has_private_mem is defined
From: Binbin Wu @ 2025-11-13  1:42 UTC (permalink / raw)
  To: Ackerley Tng
  Cc: cgroups, kvm, linux-doc, linux-fsdevel, linux-kernel,
	linux-kselftest, linux-mm, linux-trace-kernel, x86, akpm, bp,
	brauner, chao.p.peng, chenhuacai, corbet, dave.hansen,
	dave.hansen, david, dmatlack, erdemaktas, fan.du, fvdl, haibo1.xu,
	hannes, hch, hpa, hughd, ira.weiny, isaku.yamahata, jack,
	james.morse, jarkko, jgg, jgowans, jhubbard, jroedel, jthoughton,
	jun.miao, kai.huang, keirf, kent.overstreet, liam.merwick,
	maciej.wieczor-retman, mail, maobibo, mathieu.desnoyers, maz,
	mhiramat, mhocko, mic, michael.roth, mingo, mlevitsk, mpe,
	muchun.song, nikunj, nsaenz, oliver.upton, palmer, pankaj.gupta,
	paul.walmsley, pbonzini, peterx, pgonda, prsampat, pvorel,
	qperret, richard.weiyang, rick.p.edgecombe, rientjes, rostedt,
	roypat, rppt, seanjc, shakeel.butt, shuah, steven.price,
	steven.sistare, suzuki.poulose, tabba, tglx, thomas.lendacky,
	vannapurve, vbabka, viro, vkuznets, wei.w.wang, will, willy,
	wyihan, xiaoyao.li, yan.y.zhao, yilun.xu, yuzenghui, zhiquan1.li
In-Reply-To: <405686bacd68ce6c76aa5e6ef40f0a5324983c5b.1760731772.git.ackerleytng@google.com>



On 10/18/2025 4:11 AM, Ackerley Tng wrote:
> From: Sean Christopherson <seanjc@google.com>
>
> Explicitly guard reporting support for KVM_MEMORY_ATTRIBUTE_PRIVATE based
> on kvm_arch_has_private_mem being #defined in anticipation of decoupling
> kvm_supported_mem_attributes() from CONFIG_KVM_VM_MEMORY_ATTRIBUTES.
> guest_memfd support for memory attributes will be unconditional to avoid
> yet more macros (all architectures that support guest_memfd are expect to
  expect -> expected

> user per-gmem attributes at some point), at which point enumerating support
    ^
   use
> KVM_MEMORY_ATTRIBUTE_PRIVATE based solely on memory attributes being
> supported _somewhere_ would result in KVM over-reporting support on arm64.
>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
>   include/linux/kvm_host.h | 2 +-
>   virt/kvm/kvm_main.c      | 2 ++
>   2 files changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index fddb373fcbaaf..21bf30e8d3cc1 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -721,7 +721,7 @@ static inline int kvm_arch_vcpu_memslots_id(struct kvm_vcpu *vcpu)
>   }
>   #endif
>   
> -#ifndef CONFIG_KVM_VM_MEMORY_ATTRIBUTES
> +#ifndef kvm_arch_has_private_mem
>   static inline bool kvm_arch_has_private_mem(struct kvm *kvm)
>   {
>   	return false;
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index f73047ea4333e..591795a3fa124 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -2428,8 +2428,10 @@ static int kvm_vm_ioctl_clear_dirty_log(struct kvm *kvm,
>   #ifdef CONFIG_KVM_VM_MEMORY_ATTRIBUTES
>   static u64 kvm_supported_mem_attributes(struct kvm *kvm)
>   {
> +#ifdef kvm_arch_has_private_mem
>   	if (!kvm || kvm_arch_has_private_mem(kvm))
>   		return KVM_MEMORY_ATTRIBUTE_PRIVATE;
> +#endif
>   
>   	return 0;
>   }


^ permalink raw reply

* Re: [PATCH v4] trace/pid_list: optimize pid_list->lock contention
From: Steven Rostedt @ 2025-11-13  1:02 UTC (permalink / raw)
  To: Yongliang Gao
  Cc: mhiramat, mathieu.desnoyers, bigeasy, linux-kernel,
	linux-trace-kernel, frankjpliu, Yongliang Gao, Huang Cun
In-Reply-To: <20251113004526.1129666-1-leonylgao@gmail.com>

On Thu, 13 Nov 2025 08:45:26 +0800
Yongliang Gao <leonylgao@gmail.com> wrote:

> ---
> Changes from v3:
> - Fixed patch format as per feedback. [Steven Rostedt]
> - Link to v3: https://lore.kernel.org/all/20251113000252.1058144-1-leonylgao@gmail.com

I already pulled this in and started testing it. No need for this resend.

-- Steve

^ permalink raw reply

* [PATCH v4] trace/pid_list: optimize pid_list->lock contention
From: Yongliang Gao @ 2025-11-13  0:45 UTC (permalink / raw)
  To: rostedt, mhiramat, mathieu.desnoyers, bigeasy
  Cc: linux-kernel, linux-trace-kernel, frankjpliu, Yongliang Gao,
	Huang Cun

From: Yongliang Gao <leonylgao@tencent.com>

When the system has many cores and task switching is frequent,
setting set_ftrace_pid can cause frequent pid_list->lock contention
and high system sys usage.

For example, in a 288-core VM environment, we observed 267 CPUs
experiencing contention on pid_list->lock, with stack traces showing:

 #4 [ffffa6226fb4bc70] native_queued_spin_lock_slowpath at ffffffff99cd4b7e
 #5 [ffffa6226fb4bc90] _raw_spin_lock_irqsave at ffffffff99cd3e36
 #6 [ffffa6226fb4bca0] trace_pid_list_is_set at ffffffff99267554
 #7 [ffffa6226fb4bcc0] trace_ignore_this_task at ffffffff9925c288
 #8 [ffffa6226fb4bcd8] ftrace_filter_pid_sched_switch_probe at ffffffff99246efe
 #9 [ffffa6226fb4bcf0] __schedule at ffffffff99ccd161

Replaces the existing spinlock with a seqlock to allow concurrent readers,
while maintaining write exclusivity.

Signed-off-by: Yongliang Gao <leonylgao@tencent.com>
Reviewed-by: Huang Cun <cunhuang@tencent.com>

---
Changes from v3:
- Fixed patch format as per feedback. [Steven Rostedt]
- Link to v3: https://lore.kernel.org/all/20251113000252.1058144-1-leonylgao@gmail.com
Changes from v2:
- Keep trace_pid_list_next() using raw_spin_lock for simplicity. [Steven Rostedt]
- Link to v2: https://lore.kernel.org/all/20251112181456.473864-1-leonylgao@gmail.com
Changes from v1:
- Fixed sleep-in-atomic issues under PREEMPT_RT. [Steven Rostedt]
- Link to v1: https://lore.kernel.org/all/20251015114952.4014352-1-leonylgao@gmail.com
---
 kernel/trace/pid_list.c | 30 +++++++++++++++++++++---------
 kernel/trace/pid_list.h |  1 +
 2 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/kernel/trace/pid_list.c b/kernel/trace/pid_list.c
index 090bb5ea4a19..dbee72d69d0a 100644
--- a/kernel/trace/pid_list.c
+++ b/kernel/trace/pid_list.c
@@ -3,6 +3,7 @@
  * Copyright (C) 2021 VMware Inc, Steven Rostedt <rostedt@goodmis.org>
  */
 #include <linux/spinlock.h>
+#include <linux/seqlock.h>
 #include <linux/irq_work.h>
 #include <linux/slab.h>
 #include "trace.h"
@@ -126,7 +127,7 @@ bool trace_pid_list_is_set(struct trace_pid_list *pid_list, unsigned int pid)
 {
 	union upper_chunk *upper_chunk;
 	union lower_chunk *lower_chunk;
-	unsigned long flags;
+	unsigned int seq;
 	unsigned int upper1;
 	unsigned int upper2;
 	unsigned int lower;
@@ -138,14 +139,16 @@ bool trace_pid_list_is_set(struct trace_pid_list *pid_list, unsigned int pid)
 	if (pid_split(pid, &upper1, &upper2, &lower) < 0)
 		return false;
 
-	raw_spin_lock_irqsave(&pid_list->lock, flags);
-	upper_chunk = pid_list->upper[upper1];
-	if (upper_chunk) {
-		lower_chunk = upper_chunk->data[upper2];
-		if (lower_chunk)
-			ret = test_bit(lower, lower_chunk->data);
-	}
-	raw_spin_unlock_irqrestore(&pid_list->lock, flags);
+	do {
+		seq = read_seqcount_begin(&pid_list->seqcount);
+		ret = false;
+		upper_chunk = pid_list->upper[upper1];
+		if (upper_chunk) {
+			lower_chunk = upper_chunk->data[upper2];
+			if (lower_chunk)
+				ret = test_bit(lower, lower_chunk->data);
+		}
+	} while (read_seqcount_retry(&pid_list->seqcount, seq));
 
 	return ret;
 }
@@ -178,6 +181,7 @@ int trace_pid_list_set(struct trace_pid_list *pid_list, unsigned int pid)
 		return -EINVAL;
 
 	raw_spin_lock_irqsave(&pid_list->lock, flags);
+	write_seqcount_begin(&pid_list->seqcount);
 	upper_chunk = pid_list->upper[upper1];
 	if (!upper_chunk) {
 		upper_chunk = get_upper_chunk(pid_list);
@@ -199,6 +203,7 @@ int trace_pid_list_set(struct trace_pid_list *pid_list, unsigned int pid)
 	set_bit(lower, lower_chunk->data);
 	ret = 0;
  out:
+	write_seqcount_end(&pid_list->seqcount);
 	raw_spin_unlock_irqrestore(&pid_list->lock, flags);
 	return ret;
 }
@@ -230,6 +235,7 @@ int trace_pid_list_clear(struct trace_pid_list *pid_list, unsigned int pid)
 		return -EINVAL;
 
 	raw_spin_lock_irqsave(&pid_list->lock, flags);
+	write_seqcount_begin(&pid_list->seqcount);
 	upper_chunk = pid_list->upper[upper1];
 	if (!upper_chunk)
 		goto out;
@@ -250,6 +256,7 @@ int trace_pid_list_clear(struct trace_pid_list *pid_list, unsigned int pid)
 		}
 	}
  out:
+	write_seqcount_end(&pid_list->seqcount);
 	raw_spin_unlock_irqrestore(&pid_list->lock, flags);
 	return 0;
 }
@@ -340,8 +347,10 @@ static void pid_list_refill_irq(struct irq_work *iwork)
 
  again:
 	raw_spin_lock(&pid_list->lock);
+	write_seqcount_begin(&pid_list->seqcount);
 	upper_count = CHUNK_ALLOC - pid_list->free_upper_chunks;
 	lower_count = CHUNK_ALLOC - pid_list->free_lower_chunks;
+	write_seqcount_end(&pid_list->seqcount);
 	raw_spin_unlock(&pid_list->lock);
 
 	if (upper_count <= 0 && lower_count <= 0)
@@ -370,6 +379,7 @@ static void pid_list_refill_irq(struct irq_work *iwork)
 	}
 
 	raw_spin_lock(&pid_list->lock);
+	write_seqcount_begin(&pid_list->seqcount);
 	if (upper) {
 		*upper_next = pid_list->upper_list;
 		pid_list->upper_list = upper;
@@ -380,6 +390,7 @@ static void pid_list_refill_irq(struct irq_work *iwork)
 		pid_list->lower_list = lower;
 		pid_list->free_lower_chunks += lcnt;
 	}
+	write_seqcount_end(&pid_list->seqcount);
 	raw_spin_unlock(&pid_list->lock);
 
 	/*
@@ -419,6 +430,7 @@ struct trace_pid_list *trace_pid_list_alloc(void)
 	init_irq_work(&pid_list->refill_irqwork, pid_list_refill_irq);
 
 	raw_spin_lock_init(&pid_list->lock);
+	seqcount_raw_spinlock_init(&pid_list->seqcount, &pid_list->lock);
 
 	for (i = 0; i < CHUNK_ALLOC; i++) {
 		union upper_chunk *chunk;
diff --git a/kernel/trace/pid_list.h b/kernel/trace/pid_list.h
index 62e73f1ac85f..0b45fb0eadb9 100644
--- a/kernel/trace/pid_list.h
+++ b/kernel/trace/pid_list.h
@@ -76,6 +76,7 @@ union upper_chunk {
 };
 
 struct trace_pid_list {
+	seqcount_raw_spinlock_t		seqcount;
 	raw_spinlock_t			lock;
 	struct irq_work			refill_irqwork;
 	union upper_chunk		*upper[UPPER1_SIZE]; // 1 or 2K in size
-- 
2.43.5


^ permalink raw reply related

* Re: [PATCH v3] trace/pid_list: optimize pid_list->lock contention
From: Steven Rostedt @ 2025-11-13  0:21 UTC (permalink / raw)
  To: Yongliang Gao
  Cc: mhiramat, mathieu.desnoyers, bigeasy, linux-kernel,
	linux-trace-kernel, frankjpliu, Yongliang Gao, Huang Cun
In-Reply-To: <20251113000252.1058144-1-leonylgao@gmail.com>

On Thu, 13 Nov 2025 08:02:52 +0800
Yongliang Gao <leonylgao@gmail.com> wrote:

> From: Yongliang Gao <leonylgao@tencent.com>
> 
> When the system has many cores and task switching is frequent,
> setting set_ftrace_pid can cause frequent pid_list->lock contention
> and high system sys usage.
> 
> For example, in a 288-core VM environment, we observed 267 CPUs
> experiencing contention on pid_list->lock, with stack traces showing:
> 
>  #4 [ffffa6226fb4bc70] native_queued_spin_lock_slowpath at ffffffff99cd4b7e
>  #5 [ffffa6226fb4bc90] _raw_spin_lock_irqsave at ffffffff99cd3e36
>  #6 [ffffa6226fb4bca0] trace_pid_list_is_set at ffffffff99267554
>  #7 [ffffa6226fb4bcc0] trace_ignore_this_task at ffffffff9925c288
>  #8 [ffffa6226fb4bcd8] ftrace_filter_pid_sched_switch_probe at ffffffff99246efe
>  #9 [ffffa6226fb4bcf0] __schedule at ffffffff99ccd161
> 
> Replaces the existing spinlock with a seqlock to allow concurrent readers,
> while maintaining write exclusivity.
> 
> ---
> Changes from v2:
> - Keep trace_pid_list_next() using raw_spin_lock for simplicity. [Steven Rostedt]
> - Link to v2: https://lore.kernel.org/all/20251112181456.473864-1-leonylgao@gmail.com
> Changes from v1:
> - Fixed sleep-in-atomic issues under PREEMPT_RT. [Steven Rostedt]
> - Link to v1: https://lore.kernel.org/all/20251015114952.4014352-1-leonylgao@gmail.com
> ---

You don't need to resend, but the "Changes from" needs to go below the
'---' after the tags. Otherwise, git am removes everything from the above
'---', including your tags below.

-- Steve


> 
> Signed-off-by: Yongliang Gao <leonylgao@tencent.com>
> Reviewed-by: Huang Cun <cunhuang@tencent.com>
> ---
>  kernel/trace/pid_list.c | 30 +++++++++++++++++++++---------
>  kernel/trace/pid_list.h |  1 +
>  2 files changed, 22 insertions(+), 9 deletions(-)
> 

^ permalink raw reply

* [PATCH v3] trace/pid_list: optimize pid_list->lock contention
From: Yongliang Gao @ 2025-11-13  0:02 UTC (permalink / raw)
  To: rostedt, mhiramat, mathieu.desnoyers, bigeasy
  Cc: linux-kernel, linux-trace-kernel, frankjpliu, Yongliang Gao,
	Huang Cun

From: Yongliang Gao <leonylgao@tencent.com>

When the system has many cores and task switching is frequent,
setting set_ftrace_pid can cause frequent pid_list->lock contention
and high system sys usage.

For example, in a 288-core VM environment, we observed 267 CPUs
experiencing contention on pid_list->lock, with stack traces showing:

 #4 [ffffa6226fb4bc70] native_queued_spin_lock_slowpath at ffffffff99cd4b7e
 #5 [ffffa6226fb4bc90] _raw_spin_lock_irqsave at ffffffff99cd3e36
 #6 [ffffa6226fb4bca0] trace_pid_list_is_set at ffffffff99267554
 #7 [ffffa6226fb4bcc0] trace_ignore_this_task at ffffffff9925c288
 #8 [ffffa6226fb4bcd8] ftrace_filter_pid_sched_switch_probe at ffffffff99246efe
 #9 [ffffa6226fb4bcf0] __schedule at ffffffff99ccd161

Replaces the existing spinlock with a seqlock to allow concurrent readers,
while maintaining write exclusivity.

---
Changes from v2:
- Keep trace_pid_list_next() using raw_spin_lock for simplicity. [Steven Rostedt]
- Link to v2: https://lore.kernel.org/all/20251112181456.473864-1-leonylgao@gmail.com
Changes from v1:
- Fixed sleep-in-atomic issues under PREEMPT_RT. [Steven Rostedt]
- Link to v1: https://lore.kernel.org/all/20251015114952.4014352-1-leonylgao@gmail.com
---

Signed-off-by: Yongliang Gao <leonylgao@tencent.com>
Reviewed-by: Huang Cun <cunhuang@tencent.com>
---
 kernel/trace/pid_list.c | 30 +++++++++++++++++++++---------
 kernel/trace/pid_list.h |  1 +
 2 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/kernel/trace/pid_list.c b/kernel/trace/pid_list.c
index 090bb5ea4a19..dbee72d69d0a 100644
--- a/kernel/trace/pid_list.c
+++ b/kernel/trace/pid_list.c
@@ -3,6 +3,7 @@
  * Copyright (C) 2021 VMware Inc, Steven Rostedt <rostedt@goodmis.org>
  */
 #include <linux/spinlock.h>
+#include <linux/seqlock.h>
 #include <linux/irq_work.h>
 #include <linux/slab.h>
 #include "trace.h"
@@ -126,7 +127,7 @@ bool trace_pid_list_is_set(struct trace_pid_list *pid_list, unsigned int pid)
 {
 	union upper_chunk *upper_chunk;
 	union lower_chunk *lower_chunk;
-	unsigned long flags;
+	unsigned int seq;
 	unsigned int upper1;
 	unsigned int upper2;
 	unsigned int lower;
@@ -138,14 +139,16 @@ bool trace_pid_list_is_set(struct trace_pid_list *pid_list, unsigned int pid)
 	if (pid_split(pid, &upper1, &upper2, &lower) < 0)
 		return false;
 
-	raw_spin_lock_irqsave(&pid_list->lock, flags);
-	upper_chunk = pid_list->upper[upper1];
-	if (upper_chunk) {
-		lower_chunk = upper_chunk->data[upper2];
-		if (lower_chunk)
-			ret = test_bit(lower, lower_chunk->data);
-	}
-	raw_spin_unlock_irqrestore(&pid_list->lock, flags);
+	do {
+		seq = read_seqcount_begin(&pid_list->seqcount);
+		ret = false;
+		upper_chunk = pid_list->upper[upper1];
+		if (upper_chunk) {
+			lower_chunk = upper_chunk->data[upper2];
+			if (lower_chunk)
+				ret = test_bit(lower, lower_chunk->data);
+		}
+	} while (read_seqcount_retry(&pid_list->seqcount, seq));
 
 	return ret;
 }
@@ -178,6 +181,7 @@ int trace_pid_list_set(struct trace_pid_list *pid_list, unsigned int pid)
 		return -EINVAL;
 
 	raw_spin_lock_irqsave(&pid_list->lock, flags);
+	write_seqcount_begin(&pid_list->seqcount);
 	upper_chunk = pid_list->upper[upper1];
 	if (!upper_chunk) {
 		upper_chunk = get_upper_chunk(pid_list);
@@ -199,6 +203,7 @@ int trace_pid_list_set(struct trace_pid_list *pid_list, unsigned int pid)
 	set_bit(lower, lower_chunk->data);
 	ret = 0;
  out:
+	write_seqcount_end(&pid_list->seqcount);
 	raw_spin_unlock_irqrestore(&pid_list->lock, flags);
 	return ret;
 }
@@ -230,6 +235,7 @@ int trace_pid_list_clear(struct trace_pid_list *pid_list, unsigned int pid)
 		return -EINVAL;
 
 	raw_spin_lock_irqsave(&pid_list->lock, flags);
+	write_seqcount_begin(&pid_list->seqcount);
 	upper_chunk = pid_list->upper[upper1];
 	if (!upper_chunk)
 		goto out;
@@ -250,6 +256,7 @@ int trace_pid_list_clear(struct trace_pid_list *pid_list, unsigned int pid)
 		}
 	}
  out:
+	write_seqcount_end(&pid_list->seqcount);
 	raw_spin_unlock_irqrestore(&pid_list->lock, flags);
 	return 0;
 }
@@ -340,8 +347,10 @@ static void pid_list_refill_irq(struct irq_work *iwork)
 
  again:
 	raw_spin_lock(&pid_list->lock);
+	write_seqcount_begin(&pid_list->seqcount);
 	upper_count = CHUNK_ALLOC - pid_list->free_upper_chunks;
 	lower_count = CHUNK_ALLOC - pid_list->free_lower_chunks;
+	write_seqcount_end(&pid_list->seqcount);
 	raw_spin_unlock(&pid_list->lock);
 
 	if (upper_count <= 0 && lower_count <= 0)
@@ -370,6 +379,7 @@ static void pid_list_refill_irq(struct irq_work *iwork)
 	}
 
 	raw_spin_lock(&pid_list->lock);
+	write_seqcount_begin(&pid_list->seqcount);
 	if (upper) {
 		*upper_next = pid_list->upper_list;
 		pid_list->upper_list = upper;
@@ -380,6 +390,7 @@ static void pid_list_refill_irq(struct irq_work *iwork)
 		pid_list->lower_list = lower;
 		pid_list->free_lower_chunks += lcnt;
 	}
+	write_seqcount_end(&pid_list->seqcount);
 	raw_spin_unlock(&pid_list->lock);
 
 	/*
@@ -419,6 +430,7 @@ struct trace_pid_list *trace_pid_list_alloc(void)
 	init_irq_work(&pid_list->refill_irqwork, pid_list_refill_irq);
 
 	raw_spin_lock_init(&pid_list->lock);
+	seqcount_raw_spinlock_init(&pid_list->seqcount, &pid_list->lock);
 
 	for (i = 0; i < CHUNK_ALLOC; i++) {
 		union upper_chunk *chunk;
diff --git a/kernel/trace/pid_list.h b/kernel/trace/pid_list.h
index 62e73f1ac85f..0b45fb0eadb9 100644
--- a/kernel/trace/pid_list.h
+++ b/kernel/trace/pid_list.h
@@ -76,6 +76,7 @@ union upper_chunk {
 };
 
 struct trace_pid_list {
+	seqcount_raw_spinlock_t		seqcount;
 	raw_spinlock_t			lock;
 	struct irq_work			refill_irqwork;
 	union upper_chunk		*upper[UPPER1_SIZE]; // 1 or 2K in size
-- 
2.43.5


^ permalink raw reply related

* [PATCH v1] cpufreq: Add policy_frequency trace event
From: Samuel Wu @ 2025-11-12 23:51 UTC (permalink / raw)
  To: Rafael J. Wysocki, Viresh Kumar, Steven Rostedt, Masami Hiramatsu,
	Mathieu Desnoyers
  Cc: Samuel Wu, kernel-team, linux-pm, linux-kernel,
	linux-trace-kernel

The existing cpu_frequency trace_event can be verbose, emitting an event
for every CPU in the policy even when their frequencies are identical.

This patch adds a new policy_frequency trace event, which provides a
more efficient alternative to cpu_frequency trace event. This option
allows users who only need frequency at a policy level more concise logs
with simpler analysis.

Signed-off-by: Samuel Wu <wusamuel@google.com>
---
 drivers/cpufreq/cpufreq.c    |  2 ++
 include/trace/events/power.h | 21 +++++++++++++++++++++
 2 files changed, 23 insertions(+)

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 4472bb1ec83c..b65534a4fd9a 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -345,6 +345,7 @@ static void cpufreq_notify_transition(struct cpufreq_policy *policy,
 		pr_debug("FREQ: %u - CPUs: %*pbl\n", freqs->new,
 			 cpumask_pr_args(policy->cpus));
 
+		trace_policy_frequency(freqs->new, policy->cpu);
 		for_each_cpu(cpu, policy->cpus)
 			trace_cpu_frequency(freqs->new, cpu);
 
@@ -2214,6 +2215,7 @@ unsigned int cpufreq_driver_fast_switch(struct cpufreq_policy *policy,
 			    arch_scale_freq_ref(policy->cpu));
 	cpufreq_stats_record_transition(policy, freq);
 
+	trace_policy_frequency(freq, policy->cpu);
 	if (trace_cpu_frequency_enabled()) {
 		for_each_cpu(cpu, policy->cpus)
 			trace_cpu_frequency(freq, cpu);
diff --git a/include/trace/events/power.h b/include/trace/events/power.h
index 82904291c2b8..87dbd53c8ea1 100644
--- a/include/trace/events/power.h
+++ b/include/trace/events/power.h
@@ -188,6 +188,27 @@ DEFINE_EVENT(cpu, cpu_frequency,
 	TP_ARGS(frequency, cpu_id)
 );
 
+TRACE_EVENT(policy_frequency,
+
+	TP_PROTO(unsigned int frequency, unsigned int policy_cpu),
+
+	TP_ARGS(frequency, policy_cpu),
+
+	TP_STRUCT__entry(
+		__field(u32, frequency)
+		__field(u32, policy_cpu)
+	),
+
+	TP_fast_assign(
+		__entry->frequency = frequency;
+		__entry->policy_cpu = policy_cpu;
+	),
+
+	TP_printk("frequency=%lu policy_cpu=%lu",
+		  (unsigned long)__entry->frequency,
+		  (unsigned long)__entry->policy_cpu)
+);
+
 TRACE_EVENT(cpu_frequency_limits,
 
 	TP_PROTO(struct cpufreq_policy *policy),
-- 
2.51.2.1041.gc1ab5b90ca-goog


^ permalink raw reply related

* Re: [PATCH v16 4/4] perf tools: Merge deferred user callchains
From: Namhyung Kim @ 2025-11-12 22:38 UTC (permalink / raw)
  To: Jens Remus
  Cc: Steven Rostedt, Steven Rostedt, linux-kernel, linux-trace-kernel,
	bpf, x86, Masami Hiramatsu, Mathieu Desnoyers, Josh Poimboeuf,
	Ingo Molnar, Jiri Olsa, Thomas Gleixner, Andrii Nakryiko,
	Indu Bhagat, Jose E. Marchesi, Beau Belgrave, Linus Torvalds,
	Andrew Morton, Florian Weimer, Sam James, Kees Cook,
	Carlos O'Donell, Arnaldo Carvalho de Melo, Peter Zijlstra
In-Reply-To: <f543231e-a71c-4600-9cf3-f999ca104d86@linux.ibm.com>

Hello,

On Wed, Nov 12, 2025 at 11:05:59AM +0100, Jens Remus wrote:
> Hello Namhyung,
> 
> could you please adapt your patches from this series to Peter's latest
> changes to unwind user and related perf support, especially his new
> version c69993ecdd4d ("perf: Support deferred user unwind") available
> at:
> 
> git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git perf/core

Sure, will take a look.

Thanks,
Namhyung

> 
> On 10/24/2025 3:02 PM, Peter Zijlstra wrote:
> > On Thu, Oct 02, 2025 at 01:49:38PM -0400, Steven Rostedt wrote:
> >> On Mon, 08 Sep 2025 13:53:23 -0400
> >> Steven Rostedt <rostedt@kernel.org> wrote:
> >>
> >>> +static int evlist__deliver_deferred_samples(struct evlist *evlist,
> >>> +					    const struct perf_tool *tool,
> >>> +					    union  perf_event *event,
> >>> +					    struct perf_sample *sample,
> >>> +					    struct machine *machine)
> >>> +{
> >>> +	struct deferred_event *de, *tmp;
> >>> +	struct evsel *evsel;
> >>> +	int ret = 0;
> >>> +
> >>> +	if (!tool->merge_deferred_callchains) {
> >>> +		evsel = evlist__id2evsel(evlist, sample->id);
> >>> +		return tool->callchain_deferred(tool, event, sample,
> >>> +						evsel, machine);
> >>> +	}
> >>> +
> >>> +	list_for_each_entry_safe(de, tmp, &evlist->deferred_samples, list) {
> >>> +		struct perf_sample orig_sample;
> >>
> >> orig_sample is not initialized and can then contain junk.
> >>
> >>> +
> >>> +		ret = evlist__parse_sample(evlist, de->event, &orig_sample);
> >>> +		if (ret < 0) {
> >>> +			pr_err("failed to parse original sample\n");
> >>> +			break;
> >>> +		}
> >>> +
> >>> +		if (sample->tid != orig_sample.tid)
> >>> +			continue;
> >>> +
> >>> +		if (event->callchain_deferred.cookie == orig_sample.deferred_cookie)
> >>> +			sample__merge_deferred_callchain(&orig_sample, sample);
> >>
> >> The sample__merge_deferred_callchain() initializes both
> >> orig_sample.deferred_callchain and the callchain. But now that it's not
> >> being called, it can cause the below free to happen with junk as the
> >> callchain. This needs:
> >>
> >> 		else
> >> 			orig_sample.deferred_callchain = false;
> > 
> > Ah, so I saw crashes from here and just deleted both free()s and got on
> > with things ;-)
> 
> This needs to be properly resolved.  In the meantime I am using Steven's
> suggestion above to continue my work on unwind user sframe (s390).
> 
> > 
> >>> +
> >>> +		evsel = evlist__id2evsel(evlist, orig_sample.id);
> >>> +		ret = evlist__deliver_sample(evlist, tool, de->event,
> >>> +					     &orig_sample, evsel,> machine); +
> >>> +		if (orig_sample.deferred_callchain)
> >>> +			free(orig_sample.callchain);
> >>> +
> >>> +		list_del(&de->list);
> >>> +		free(de);
> >>> +
> >>> +		if (ret)
> >>> +			break;
> >>> +	}
> >>> +	return ret;
> >>> +}
> >>
> >> -- Steve
> 
> Thanks and regards,
> Jens
> -- 
> Jens Remus
> Linux on Z Development (D3303)
> +49-7031-16-1128 Office
> jremus@de.ibm.com
> 
> IBM
> 
> IBM Deutschland Research & Development GmbH; Vorsitzender des Aufsichtsrats: Wolfgang Wendt; Geschäftsführung: David Faller; Sitz der Gesellschaft: Böblingen; Registergericht: Amtsgericht Stuttgart, HRB 243294
> IBM Data Privacy Statement: https://www.ibm.com/privacy/
> 

^ permalink raw reply

* Re: [RFC PATCH 0/8] xfs: single block atomic writes for buffered IO
From: Dave Chinner @ 2025-11-12 21:56 UTC (permalink / raw)
  To: Ojaswin Mujoo
  Cc: Christian Brauner, djwong, ritesh.list, john.g.garry, tytso,
	willy, dchinner, hch, linux-xfs, linux-kernel, linux-ext4,
	linux-fsdevel, linux-mm, jack, nilay, martin.petersen, rostedt,
	axboe, linux-block, linux-trace-kernel
In-Reply-To: <cover.1762945505.git.ojaswin@linux.ibm.com>

On Wed, Nov 12, 2025 at 04:36:03PM +0530, Ojaswin Mujoo wrote:
> This patch adds support to perform single block RWF_ATOMIC writes for
> iomap xfs buffered IO. This builds upon the inital RFC shared by John
> Garry last year [1]. Most of the details are present in the respective 
> commit messages but I'd mention some of the design points below:

What is the use case for this functionality? i.e. what is the
reason for adding all this complexity?

-Dave.
-- 
Dave Chinner
david@fromorbit.com

^ permalink raw reply

* Re: [PATCH v2 19/21] scsi: fnic: Switch to use %ptS
From: Martin K. Petersen @ 2025-11-12 21:12 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Corey Minyard, Christian König, Dr. David Alan Gilbert,
	Alex Deucher, Thomas Zimmermann, Dmitry Baryshkov, Rob Clark,
	Matthew Brost, Ulf Hansson, Vitaly Lifshits,
	Manivannan Sadhasivam, Niklas Cassel, Calvin Owens,
	Vadim Fedorenko, Sagi Maimon, Martin K. Petersen,
	Karan Tilak Kumar, Hans Verkuil, Casey Schaufler, Steven Rostedt,
	Petr Mladek, Viacheslav Dubeyko, Max Kellermann, linux-doc,
	linux-kernel, openipmi-developer, linux-media, dri-devel,
	linaro-mm-sig, amd-gfx, linux-arm-msm, freedreno, intel-xe,
	linux-mmc, netdev, intel-wired-lan, linux-pci, linux-s390,
	linux-scsi, linux-staging, ceph-devel, linux-trace-kernel,
	Rasmus Villemoes, Sergey Senozhatsky, Jonathan Corbet,
	Sumit Semwal, Gustavo Padovan, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Dmitry Baryshkov, Abhinav Kumar,
	Jessica Zhang, Sean Paul, Marijn Suijten, Konrad Dybcio,
	Lucas De Marchi, Thomas Hellström, Rodrigo Vivi,
	Vladimir Oltean, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Tony Nguyen, Przemek Kitszel,
	Krzysztof Wilczyński, Kishon Vijay Abraham I, Bjorn Helgaas,
	Rodolfo Giometti, Richard Cochran, Jonathan Lemon,
	Stefan Haberland, Jan Hoeppner, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Satish Kharat, Sesidhar Baddela, James E.J. Bottomley,
	Mauro Carvalho Chehab, Greg Kroah-Hartman, Xiubo Li, Ilya Dryomov,
	Masami Hiramatsu, Mathieu Desnoyers, Andrew Morton
In-Reply-To: <20251111122735.880607-20-andriy.shevchenko@linux.intel.com>


Andy,

> Use %ptS instead of open coded variants to print content of
> struct timespec64 in human readable format.

Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>

-- 
Martin K. Petersen

^ permalink raw reply

* Re: [PATCH v2 20/21] scsi: snic: Switch to use %ptSp
From: Martin K. Petersen @ 2025-11-12 21:11 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Corey Minyard, Christian König, Dr. David Alan Gilbert,
	Alex Deucher, Thomas Zimmermann, Dmitry Baryshkov, Rob Clark,
	Matthew Brost, Ulf Hansson, Vitaly Lifshits,
	Manivannan Sadhasivam, Niklas Cassel, Calvin Owens,
	Vadim Fedorenko, Sagi Maimon, Martin K. Petersen,
	Karan Tilak Kumar, Hans Verkuil, Casey Schaufler, Steven Rostedt,
	Petr Mladek, Viacheslav Dubeyko, Max Kellermann, linux-doc,
	linux-kernel, openipmi-developer, linux-media, dri-devel,
	linaro-mm-sig, amd-gfx, linux-arm-msm, freedreno, intel-xe,
	linux-mmc, netdev, intel-wired-lan, linux-pci, linux-s390,
	linux-scsi, linux-staging, ceph-devel, linux-trace-kernel,
	Rasmus Villemoes, Sergey Senozhatsky, Jonathan Corbet,
	Sumit Semwal, Gustavo Padovan, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Dmitry Baryshkov, Abhinav Kumar,
	Jessica Zhang, Sean Paul, Marijn Suijten, Konrad Dybcio,
	Lucas De Marchi, Thomas Hellström, Rodrigo Vivi,
	Vladimir Oltean, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Tony Nguyen, Przemek Kitszel,
	Krzysztof Wilczyński, Kishon Vijay Abraham I, Bjorn Helgaas,
	Rodolfo Giometti, Richard Cochran, Jonathan Lemon,
	Stefan Haberland, Jan Hoeppner, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Satish Kharat, Sesidhar Baddela, James E.J. Bottomley,
	Mauro Carvalho Chehab, Greg Kroah-Hartman, Xiubo Li, Ilya Dryomov,
	Masami Hiramatsu, Mathieu Desnoyers, Andrew Morton
In-Reply-To: <20251111122735.880607-21-andriy.shevchenko@linux.intel.com>


Andy,

> Use %ptSp instead of open coded variants to print content of
> struct timespec64 in human readable format.

Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>

-- 
Martin K. Petersen

^ permalink raw reply

* Re: [PATCH v8 00/27] mm/ksw: Introduce KStackWatch debugging tool
From: Matthew Wilcox @ 2025-11-12 20:36 UTC (permalink / raw)
  To: Jinchao Wang
  Cc: kasan-dev, linux-arm-kernel, linux-doc, linux-kernel, linux-mm,
	linux-perf-users, linux-trace-kernel, llvm, workflows, x86
In-Reply-To: <aRLmGxKVvfl5N792@ndev>

[dropping all the individual email addresses; leaving only the
mailing lists]

On Wed, Nov 12, 2025 at 10:14:29AM +0800, Jinchao Wang wrote:
> On Mon, Nov 10, 2025 at 05:33:22PM +0000, Matthew Wilcox wrote:
> > On Tue, Nov 11, 2025 at 12:35:55AM +0800, Jinchao Wang wrote:
> > > Earlier this year, I debugged a stack corruption panic that revealed the
> > > limitations of existing debugging tools. The bug persisted for 739 days
> > > before being fixed (CVE-2025-22036), and my reproduction scenario
> > > differed from the CVE report—highlighting how unpredictably these bugs
> > > manifest.
> > 
> > Well, this demonstrates the dangers of keeping this problem siloed
> > within your own exfat group.  The fix made in 1bb7ff4204b6 is wrong!
> > It was fixed properly in 7375f22495e7 which lists its Fixes: as
> > Linux-2.6.12-rc2, but that's simply the beginning of git history.
> > It's actually been there since v2.4.6.4 where it's documented as simply:
> > 
> >       - some subtle fs/buffer.c race conditions (Andrew Morton, me)
> > 
> > As far as I can tell the changes made in 1bb7ff4204b6 should be
> > reverted.
> 
> Thank you for the correction and the detailed history. I wasn't aware this
> dated back to v2.4.6.4. I'm not part of the exfat group; I simply
> encountered a bug that 1bb7ff4204b6 happened to resolve in my scenario.
> The timeline actually illustrates the exact problem KStackWatch addresses:
> a bug introduced in 2001, partially addressed in 2025, then properly fixed
> months later. The 24-year gap suggests these silent stack corruptions are
> extremely difficult to locate.

I think that's a misdiagnosis caused by not understanding the limited
circumstances in which the problem occurs.  To hit this problem, you
have to have a buffer_head allocated on the stack.  That doesn't happen
in many places:

fs/buffer.c:    struct buffer_head tmp = {
fs/direct-io.c: struct buffer_head map_bh = { 0, };
fs/ext2/super.c:        struct buffer_head tmp_bh;
fs/ext2/super.c:        struct buffer_head tmp_bh;
fs/ext4/mballoc-test.c: struct buffer_head bitmap_bh;
fs/ext4/mballoc-test.c: struct buffer_head gd_bh;
fs/gfs2/bmap.c: struct buffer_head bh;
fs/gfs2/bmap.c: struct buffer_head bh;
fs/isofs/inode.c:       struct buffer_head dummy;
fs/jfs/super.c: struct buffer_head tmp_bh;
fs/jfs/super.c: struct buffer_head tmp_bh;
fs/mpage.c:     struct buffer_head map_bh;
fs/mpage.c:     struct buffer_head map_bh;

It's far more common for buffer_heads to be allocated from slab and
attached to folios.  The other necessary condition to hit this problem
is that get_block() has to actually read the data from disk.  That's
not normal either!  Most filesystems just fill in the metadata about
the block and defer the actual read to when the data is wanted.  That's
the high-performance way to do it.

So our opportunity to catch this bug was highly limited by the fact that
we just don't run the codepaths that would allow it to trigger.

> > > Initially, I enabled KASAN, but the bug did not reproduce. Reviewing the
> > > code in __blk_flush_plug(), I found it difficult to trace all logic
> > > paths due to indirect function calls through function pointers.
> > 
> > So why is the solution here not simply to fix KASAN instead of this
> > giant patch series?
> 
> KASAN caught 7375f22495e7 because put_bh() accessed bh->b_count after
> wait_on_buffer() of another thread returned—the stack was invalid.
> In 1bb7ff4204b6 and my case, corruption occurred before the victim
> function of another thread returned. The stack remained valid to KASAN,
> so no warning triggered. This is timing-dependent, not a KASAN deficiency.

I agree that it's a narrow race window, but nevertheless KASAN did catch
it with ntfs and not with exfat.  The KASAN documentation states that
it can catch this kind of bug:

Generic KASAN supports finding bugs in all of slab, page_alloc, vmap, vmalloc,
stack, and global memory.

Software Tag-Based KASAN supports slab, page_alloc, vmalloc, and stack memory.

Hardware Tag-Based KASAN supports slab, page_alloc, and non-executable vmalloc
memory.

(hm, were you using hwkasan instead of swkasan, and that's why you
couldn't see it?)


^ permalink raw reply

* Re: [PATCH] arm64: Fix double word in comments
From: Catalin Marinas @ 2025-11-12 18:33 UTC (permalink / raw)
  To: rostedt, mhiramat, will, maz, oliver.upton, Bo Liu
  Cc: Catalin Marinas, linux-kernel, linux-trace-kernel,
	linux-arm-kernel, kvmarm
In-Reply-To: <20251029071742.17732-1-liubo03@inspur.com>

From: Catalin Marinas <catalin.marinas@arm.com>

On Wed, 29 Oct 2025 15:17:42 +0800, Bo Liu wrote:
> Remove the repeated word "the" in comments.

Applied to arm64 (for-next/typos), thanks!

[1/1] arm64: Fix double word in comments
      https://git.kernel.org/arm64/c/337f7e3a4b4d

-- 
Catalin


^ permalink raw reply

* Re: [PATCH v2] trace/pid_list: optimize pid_list->lock contention
From: Steven Rostedt @ 2025-11-12 18:29 UTC (permalink / raw)
  To: Yongliang Gao
  Cc: mhiramat, mathieu.desnoyers, bigeasy, linux-kernel,
	linux-trace-kernel, frankjpliu, Yongliang Gao, Huang Cun
In-Reply-To: <20251112181456.473864-1-leonylgao@gmail.com>

On Thu, 13 Nov 2025 02:14:56 +0800
Yongliang Gao <leonylgao@gmail.com> wrote:

> @@ -271,7 +277,6 @@ int trace_pid_list_next(struct trace_pid_list *pid_list, unsigned int pid,
>  {
>  	union upper_chunk *upper_chunk;
>  	union lower_chunk *lower_chunk;
> -	unsigned long flags;
>  	unsigned int upper1;
>  	unsigned int upper2;
>  	unsigned int lower;
> @@ -282,27 +287,44 @@ int trace_pid_list_next(struct trace_pid_list *pid_list, unsigned int pid,
>  	if (pid_split(pid, &upper1, &upper2, &lower) < 0)
>  		return -EINVAL;
>  
> -	raw_spin_lock_irqsave(&pid_list->lock, flags);
> -	for (; upper1 <= UPPER_MASK; upper1++, upper2 = 0) {
> -		upper_chunk = pid_list->upper[upper1];
> +	do {
> +		unsigned int start_upper1 = upper1;
> +		unsigned int start_upper2 = upper2;
> +		unsigned int start_lower = lower;
> +		unsigned int seq;
>  
> -		if (!upper_chunk)
> -			continue;
> +		seq = read_seqcount_begin(&pid_list->seqcount);
>  
> -		for (; upper2 <= UPPER_MASK; upper2++, lower = 0) {
> -			lower_chunk = upper_chunk->data[upper2];
> -			if (!lower_chunk)
> +		for (; upper1 <= UPPER_MASK; upper1++, upper2 = 0) {
> +			upper_chunk = pid_list->upper[upper1];
> +
> +			if (!upper_chunk)
>  				continue;
>  
> -			lower = find_next_bit(lower_chunk->data, LOWER_MAX,
> -					    lower);
> -			if (lower < LOWER_MAX)
> -				goto found;
> +			for (; upper2 <= UPPER_MASK; upper2++, lower = 0) {
> +				lower_chunk = upper_chunk->data[upper2];
> +				if (!lower_chunk)
> +					continue;
> +
> +				lower = find_next_bit(lower_chunk->data, LOWER_MAX,
> +						    lower);
> +				if (lower < LOWER_MAX)
> +					goto found;
> +			}
>  		}
> -	}
>  
> +		upper1 = UPPER_MASK + 1; /* Mark as not found */
>   found:
> -	raw_spin_unlock_irqrestore(&pid_list->lock, flags);
> +		if (read_seqcount_retry(&pid_list->seqcount, seq)) {
> +			/* Retry if write happened during read */
> +			upper1 = start_upper1;
> +			upper2 = start_upper2;
> +			lower = start_lower;
> +			continue;
> +		}
> +		break;
> +	} while (1);
> +
>  	if (upper1 > UPPER_MASK)
>  		return -1;

Honestly, I wouldn't modify trace_pid_list_next(). It is simply used for
printing of the pids in /sys/kernel/tracing/set_*_pid files. It's not a
critical section, and it shouldn't affect scheduling like
trace_pid_list_is_set() does.

Just keep it taking the raw spin lock, as that will keep it from being
modified by the writers. It also keeps the code from becoming more complex.

-- Steve


^ permalink raw reply

* [PATCH v2] trace/pid_list: optimize pid_list->lock contention
From: Yongliang Gao @ 2025-11-12 18:14 UTC (permalink / raw)
  To: rostedt, mhiramat, mathieu.desnoyers, bigeasy
  Cc: linux-kernel, linux-trace-kernel, frankjpliu, Yongliang Gao,
	Huang Cun

From: Yongliang Gao <leonylgao@tencent.com>

When the system has many cores and task switching is frequent,
setting set_ftrace_pid can cause frequent pid_list->lock contention
and high system sys usage.

For example, in a 288-core VM environment, we observed 267 CPUs
experiencing contention on pid_list->lock, with stack traces showing:

 #4 [ffffa6226fb4bc70] native_queued_spin_lock_slowpath at ffffffff99cd4b7e
 #5 [ffffa6226fb4bc90] _raw_spin_lock_irqsave at ffffffff99cd3e36
 #6 [ffffa6226fb4bca0] trace_pid_list_is_set at ffffffff99267554
 #7 [ffffa6226fb4bcc0] trace_ignore_this_task at ffffffff9925c288
 #8 [ffffa6226fb4bcd8] ftrace_filter_pid_sched_switch_probe at ffffffff99246efe
 #9 [ffffa6226fb4bcf0] __schedule at ffffffff99ccd161

Replaces the existing spinlock with a seqlock to allow concurrent readers,
while maintaining write exclusivity.

---
Changes from v1:
- Fixed sleep-in-atomic issues under PREEMPT_RT. [Steven Rostedt]
- Link to v1: https://lore.kernel.org/all/20251015114952.4014352-1-leonylgao@gmail.com
---

Signed-off-by: Yongliang Gao <leonylgao@tencent.com>
Reviewed-by: Huang Cun <cunhuang@tencent.com>
---
 kernel/trace/pid_list.c | 77 ++++++++++++++++++++++++++++-------------
 kernel/trace/pid_list.h |  1 +
 2 files changed, 53 insertions(+), 25 deletions(-)

diff --git a/kernel/trace/pid_list.c b/kernel/trace/pid_list.c
index 090bb5ea4a19..8921102543ff 100644
--- a/kernel/trace/pid_list.c
+++ b/kernel/trace/pid_list.c
@@ -2,7 +2,7 @@
 /*
  * Copyright (C) 2021 VMware Inc, Steven Rostedt <rostedt@goodmis.org>
  */
-#include <linux/spinlock.h>
+#include <linux/seqlock.h>
 #include <linux/irq_work.h>
 #include <linux/slab.h>
 #include "trace.h"
@@ -126,7 +126,7 @@ bool trace_pid_list_is_set(struct trace_pid_list *pid_list, unsigned int pid)
 {
 	union upper_chunk *upper_chunk;
 	union lower_chunk *lower_chunk;
-	unsigned long flags;
+	unsigned int seq;
 	unsigned int upper1;
 	unsigned int upper2;
 	unsigned int lower;
@@ -138,14 +138,16 @@ bool trace_pid_list_is_set(struct trace_pid_list *pid_list, unsigned int pid)
 	if (pid_split(pid, &upper1, &upper2, &lower) < 0)
 		return false;
 
-	raw_spin_lock_irqsave(&pid_list->lock, flags);
-	upper_chunk = pid_list->upper[upper1];
-	if (upper_chunk) {
-		lower_chunk = upper_chunk->data[upper2];
-		if (lower_chunk)
-			ret = test_bit(lower, lower_chunk->data);
-	}
-	raw_spin_unlock_irqrestore(&pid_list->lock, flags);
+	do {
+		seq = read_seqcount_begin(&pid_list->seqcount);
+		ret = false;
+		upper_chunk = pid_list->upper[upper1];
+		if (upper_chunk) {
+			lower_chunk = upper_chunk->data[upper2];
+			if (lower_chunk)
+				ret = test_bit(lower, lower_chunk->data);
+		}
+	} while (read_seqcount_retry(&pid_list->seqcount, seq));
 
 	return ret;
 }
@@ -178,6 +180,7 @@ int trace_pid_list_set(struct trace_pid_list *pid_list, unsigned int pid)
 		return -EINVAL;
 
 	raw_spin_lock_irqsave(&pid_list->lock, flags);
+	write_seqcount_begin(&pid_list->seqcount);
 	upper_chunk = pid_list->upper[upper1];
 	if (!upper_chunk) {
 		upper_chunk = get_upper_chunk(pid_list);
@@ -199,6 +202,7 @@ int trace_pid_list_set(struct trace_pid_list *pid_list, unsigned int pid)
 	set_bit(lower, lower_chunk->data);
 	ret = 0;
  out:
+	write_seqcount_end(&pid_list->seqcount);
 	raw_spin_unlock_irqrestore(&pid_list->lock, flags);
 	return ret;
 }
@@ -230,6 +234,7 @@ int trace_pid_list_clear(struct trace_pid_list *pid_list, unsigned int pid)
 		return -EINVAL;
 
 	raw_spin_lock_irqsave(&pid_list->lock, flags);
+	write_seqcount_begin(&pid_list->seqcount);
 	upper_chunk = pid_list->upper[upper1];
 	if (!upper_chunk)
 		goto out;
@@ -250,6 +255,7 @@ int trace_pid_list_clear(struct trace_pid_list *pid_list, unsigned int pid)
 		}
 	}
  out:
+	write_seqcount_end(&pid_list->seqcount);
 	raw_spin_unlock_irqrestore(&pid_list->lock, flags);
 	return 0;
 }
@@ -271,7 +277,6 @@ int trace_pid_list_next(struct trace_pid_list *pid_list, unsigned int pid,
 {
 	union upper_chunk *upper_chunk;
 	union lower_chunk *lower_chunk;
-	unsigned long flags;
 	unsigned int upper1;
 	unsigned int upper2;
 	unsigned int lower;
@@ -282,27 +287,44 @@ int trace_pid_list_next(struct trace_pid_list *pid_list, unsigned int pid,
 	if (pid_split(pid, &upper1, &upper2, &lower) < 0)
 		return -EINVAL;
 
-	raw_spin_lock_irqsave(&pid_list->lock, flags);
-	for (; upper1 <= UPPER_MASK; upper1++, upper2 = 0) {
-		upper_chunk = pid_list->upper[upper1];
+	do {
+		unsigned int start_upper1 = upper1;
+		unsigned int start_upper2 = upper2;
+		unsigned int start_lower = lower;
+		unsigned int seq;
 
-		if (!upper_chunk)
-			continue;
+		seq = read_seqcount_begin(&pid_list->seqcount);
 
-		for (; upper2 <= UPPER_MASK; upper2++, lower = 0) {
-			lower_chunk = upper_chunk->data[upper2];
-			if (!lower_chunk)
+		for (; upper1 <= UPPER_MASK; upper1++, upper2 = 0) {
+			upper_chunk = pid_list->upper[upper1];
+
+			if (!upper_chunk)
 				continue;
 
-			lower = find_next_bit(lower_chunk->data, LOWER_MAX,
-					    lower);
-			if (lower < LOWER_MAX)
-				goto found;
+			for (; upper2 <= UPPER_MASK; upper2++, lower = 0) {
+				lower_chunk = upper_chunk->data[upper2];
+				if (!lower_chunk)
+					continue;
+
+				lower = find_next_bit(lower_chunk->data, LOWER_MAX,
+						    lower);
+				if (lower < LOWER_MAX)
+					goto found;
+			}
 		}
-	}
 
+		upper1 = UPPER_MASK + 1; /* Mark as not found */
  found:
-	raw_spin_unlock_irqrestore(&pid_list->lock, flags);
+		if (read_seqcount_retry(&pid_list->seqcount, seq)) {
+			/* Retry if write happened during read */
+			upper1 = start_upper1;
+			upper2 = start_upper2;
+			lower = start_lower;
+			continue;
+		}
+		break;
+	} while (1);
+
 	if (upper1 > UPPER_MASK)
 		return -1;
 
@@ -340,8 +362,10 @@ static void pid_list_refill_irq(struct irq_work *iwork)
 
  again:
 	raw_spin_lock(&pid_list->lock);
+	write_seqcount_begin(&pid_list->seqcount);
 	upper_count = CHUNK_ALLOC - pid_list->free_upper_chunks;
 	lower_count = CHUNK_ALLOC - pid_list->free_lower_chunks;
+	write_seqcount_end(&pid_list->seqcount);
 	raw_spin_unlock(&pid_list->lock);
 
 	if (upper_count <= 0 && lower_count <= 0)
@@ -370,6 +394,7 @@ static void pid_list_refill_irq(struct irq_work *iwork)
 	}
 
 	raw_spin_lock(&pid_list->lock);
+	write_seqcount_begin(&pid_list->seqcount);
 	if (upper) {
 		*upper_next = pid_list->upper_list;
 		pid_list->upper_list = upper;
@@ -380,6 +405,7 @@ static void pid_list_refill_irq(struct irq_work *iwork)
 		pid_list->lower_list = lower;
 		pid_list->free_lower_chunks += lcnt;
 	}
+	write_seqcount_end(&pid_list->seqcount);
 	raw_spin_unlock(&pid_list->lock);
 
 	/*
@@ -419,6 +445,7 @@ struct trace_pid_list *trace_pid_list_alloc(void)
 	init_irq_work(&pid_list->refill_irqwork, pid_list_refill_irq);
 
 	raw_spin_lock_init(&pid_list->lock);
+	seqcount_raw_spinlock_init(&pid_list->seqcount, &pid_list->lock);
 
 	for (i = 0; i < CHUNK_ALLOC; i++) {
 		union upper_chunk *chunk;
diff --git a/kernel/trace/pid_list.h b/kernel/trace/pid_list.h
index 62e73f1ac85f..0b45fb0eadb9 100644
--- a/kernel/trace/pid_list.h
+++ b/kernel/trace/pid_list.h
@@ -76,6 +76,7 @@ union upper_chunk {
 };
 
 struct trace_pid_list {
+	seqcount_raw_spinlock_t		seqcount;
 	raw_spinlock_t			lock;
 	struct irq_work			refill_irqwork;
 	union upper_chunk		*upper[UPPER1_SIZE]; // 1 or 2K in size
-- 
2.43.5


^ permalink raw reply related

* [PATCH] MAINTAINERS: Add Tomas Glozar as a maintainer to RTLA tool
From: Steven Rostedt @ 2025-11-12 16:35 UTC (permalink / raw)
  To: LKML, Linux Trace Kernel
  Cc: Tomas Glozar, Gabriele Monaco, John Kacur, Crystal Wood,
	Linus Torvalds

From: Steven Rostedt <rostedt@goodmis.org>

Tomas will start taking over managing the changes to the Real-time Linux
Analysis (RTLA) tool. Make him officially one of the maintainers.

Also update the RTLA entry to include the linux-kernel mailing list as
well as list the patchwork and git repository that the patches will go
through.

Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
 MAINTAINERS | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 95c32cd3b524..238c3c368517 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -21634,8 +21634,12 @@ F:	tools/testing/selftests/rtc/
 
 Real-time Linux Analysis (RTLA) tools
 M:	Steven Rostedt <rostedt@goodmis.org>
+M:	Tomas Glozar <tglozar@redhat.com>
 L:	linux-trace-kernel@vger.kernel.org
+L:	linux-kernel@vger.kernel.org
 S:	Maintained
+Q:	https://patchwork.kernel.org/project/linux-trace-kernel/list/
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace.git
 F:	Documentation/tools/rtla/
 F:	tools/tracing/rtla/
 
-- 
2.51.0


^ permalink raw reply related

* Re: [PATCH] MAINTAINERS: Add Tomas Glozar as a maintainer to RTLA tool
From: Tomas Glozar @ 2025-11-12 16:41 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: LKML, Linux Trace Kernel, Gabriele Monaco, John Kacur,
	Crystal Wood, Linus Torvalds
In-Reply-To: <20251112113556.47ec9d12@gandalf.local.home>

st 12. 11. 2025 v 17:35 odesílatel Steven Rostedt <rostedt@goodmis.org> napsal:
>
> From: Steven Rostedt <rostedt@goodmis.org>
>
> Tomas will start taking over managing the changes to the Real-time Linux
> Analysis (RTLA) tool. Make him officially one of the maintainers.
>
> Also update the RTLA entry to include the linux-kernel mailing list as
> well as list the patchwork and git repository that the patches will go
> through.
>
> Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
> ---
>  MAINTAINERS | 4 ++++
>  1 file changed, 4 insertions(+)
>

Thanks.

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

Tomas


^ permalink raw reply

* Re: [RFC PATCH 2/8] mm: Add PG_atomic
From: Matthew Wilcox @ 2025-11-12 15:56 UTC (permalink / raw)
  To: Ojaswin Mujoo
  Cc: Christian Brauner, djwong, ritesh.list, john.g.garry, tytso,
	dchinner, hch, linux-xfs, linux-kernel, linux-ext4, linux-fsdevel,
	linux-mm, jack, nilay, martin.petersen, rostedt, axboe,
	linux-block, linux-trace-kernel
In-Reply-To: <5f0a7c62a3c787f2011ada10abe3826a94f99e17.1762945505.git.ojaswin@linux.ibm.com>

On Wed, Nov 12, 2025 at 04:36:05PM +0530, Ojaswin Mujoo wrote:
> From: John Garry <john.g.garry@oracle.com>
> 
> Add page flag PG_atomic, meaning that a folio needs to be written back
> atomically. This will be used by for handling RWF_ATOMIC buffered IO
> in upcoming patches.

Page flags are a precious resource.  I'm not thrilled about allocating one
to this rather niche usecase.  Wouldn't this be more aptly a flag on the
address_space rather than the folio?  ie if we're doing this kind of write
to a file, aren't most/all of the writes to the file going to be atomic?

^ permalink raw reply

* Re: [PATCH 0/5] rtla, osnoise: Fixes to address intermittent test issues
From: Crystal Wood @ 2025-11-12 15:51 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: linux-trace-kernel, John Kacur, Tomas Glozar, Costa Shulyupin,
	Wander Lairson Costa
In-Reply-To: <20251112152529.956778-1-crwood@redhat.com>

On Wed, 2025-11-12 at 09:25 -0600, Crystal Wood wrote:
> With these fixes, I'm able to run the tests in a loop overnight with no
> failures.
> 
> Crystal Wood (5):
>   rtla/tests: Don't rely on matching ^1ALL
>   tracing/osnoise: Dump stack on timerlat uret threshold event
>   tracing/osnoise: Array printk init and cleanup
>   rtla/timerlat: Exit top main loop on any non-zero wait_retval
>   rtla: Set stop threshold after all instances are enabled
> 
>  kernel/trace/trace_osnoise.c          | 46 +++++++++++++++++----------
>  tools/tracing/rtla/src/common.c       | 20 ++++++++++++
>  tools/tracing/rtla/src/common.h       |  4 +++
>  tools/tracing/rtla/src/osnoise.c      | 17 +++-------
>  tools/tracing/rtla/src/osnoise.h      |  5 ---
>  tools/tracing/rtla/src/timerlat.c     | 29 ++++++-----------
>  tools/tracing/rtla/src/timerlat_top.c |  2 +-
>  tools/tracing/rtla/tests/timerlat.t   |  2 +-
>  8 files changed, 69 insertions(+), 56 deletions(-)

Oh, forgot to mention that this is on top of Tomas's pending patches.

-Crystal


^ permalink raw reply

* [syzbot ci] Re: xfs: single block atomic writes for buffered IO
From: syzbot ci @ 2025-11-12 15:50 UTC (permalink / raw)
  To: axboe, brauner, dchinner, djwong, hch, jack, john.g.garry,
	linux-block, linux-ext4, linux-fsdevel, linux-kernel, linux-mm,
	linux-trace-kernel, linux-xfs, martin.petersen, nilay, ojaswin,
	ritesh.list, rostedt, tytso, willy
  Cc: syzbot, syzkaller-bugs
In-Reply-To: <cover.1762945505.git.ojaswin@linux.ibm.com>

syzbot ci has tested the following series

[v1] xfs: single block atomic writes for buffered IO
https://lore.kernel.org/all/cover.1762945505.git.ojaswin@linux.ibm.com
* [RFC PATCH 1/8] fs: Rename STATX{_ATTR}_WRITE_ATOMIC -> STATX{_ATTR}_WRITE_ATOMIC_DIO
* [RFC PATCH 2/8] mm: Add PG_atomic
* [RFC PATCH 3/8] fs: Add initial buffered atomic write support info to statx
* [RFC PATCH 4/8] iomap: buffered atomic write support
* [RFC PATCH 5/8] iomap: pin pages for RWF_ATOMIC buffered write
* [RFC PATCH 6/8] xfs: Report atomic write min and max for buf io as well
* [RFC PATCH 7/8] iomap: Add bs<ps buffered atomic writes support
* [RFC PATCH 8/8] xfs: Lift the bs == ps restriction for HW buffered atomic writes

and found the following issue:
KASAN: slab-out-of-bounds Read in __bitmap_clear

Full report is available here:
https://ci.syzbot.org/series/430a088a-50e2-46d3-87ff-a1f0fa67b66c

***

KASAN: slab-out-of-bounds Read in __bitmap_clear

tree:      linux-next
URL:       https://kernel.googlesource.com/pub/scm/linux/kernel/git/next/linux-next
base:      ab40c92c74c6b0c611c89516794502b3a3173966
arch:      amd64
compiler:  Debian clang version 20.1.8 (++20250708063551+0c9f909b7976-1~exp1~20250708183702.136), Debian LLD 20.1.8
config:    https://ci.syzbot.org/builds/02d3e137-5d7e-4c95-8f32-43b8663d95df/config
C repro:   https://ci.syzbot.org/findings/92a3582f-40a6-4936-8fcd-dc55c447a432/c_repro
syz repro: https://ci.syzbot.org/findings/92a3582f-40a6-4936-8fcd-dc55c447a432/syz_repro

==================================================================
BUG: KASAN: slab-out-of-bounds in __bitmap_clear+0x155/0x180 lib/bitmap.c:395
Read of size 8 at addr ffff88816ced7cd0 by task kworker/0:1/10

CPU: 0 UID: 0 PID: 10 Comm: kworker/0:1 Not tainted syzkaller #0 PREEMPT(full) 
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
Workqueue: xfs-conv/loop0 xfs_end_io
Call Trace:
 <TASK>
 dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120
 print_address_description mm/kasan/report.c:378 [inline]
 print_report+0xca/0x240 mm/kasan/report.c:482
 kasan_report+0x118/0x150 mm/kasan/report.c:595
 __bitmap_clear+0x155/0x180 lib/bitmap.c:395
 bitmap_clear include/linux/bitmap.h:496 [inline]
 ifs_clear_range_atomic fs/iomap/buffered-io.c:241 [inline]
 iomap_clear_range_atomic+0x25c/0x630 fs/iomap/buffered-io.c:268
 iomap_finish_folio_write+0x2f0/0x410 fs/iomap/buffered-io.c:1971
 iomap_finish_ioend_buffered+0x223/0x5e0 fs/iomap/ioend.c:58
 iomap_finish_ioends+0x116/0x2b0 fs/iomap/ioend.c:295
 xfs_end_ioend+0x50b/0x690 fs/xfs/xfs_aops.c:168
 xfs_end_io+0x253/0x2d0 fs/xfs/xfs_aops.c:205
 process_one_work+0x94a/0x15d0 kernel/workqueue.c:3267
 process_scheduled_works kernel/workqueue.c:3350 [inline]
 worker_thread+0x9b0/0xee0 kernel/workqueue.c:3431
 kthread+0x711/0x8a0 kernel/kthread.c:463
 ret_from_fork+0x599/0xb30 arch/x86/kernel/process.c:158
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
 </TASK>

Allocated by task 5952:
 kasan_save_stack mm/kasan/common.c:56 [inline]
 kasan_save_track+0x3e/0x80 mm/kasan/common.c:77
 poison_kmalloc_redzone mm/kasan/common.c:397 [inline]
 __kasan_kmalloc+0x93/0xb0 mm/kasan/common.c:414
 kasan_kmalloc include/linux/kasan.h:262 [inline]
 __do_kmalloc_node mm/slub.c:5672 [inline]
 __kmalloc_noprof+0x41d/0x800 mm/slub.c:5684
 kmalloc_noprof include/linux/slab.h:961 [inline]
 kzalloc_noprof include/linux/slab.h:1094 [inline]
 ifs_alloc+0x1e4/0x530 fs/iomap/buffered-io.c:356
 iomap_writeback_folio+0x81c/0x26a0 fs/iomap/buffered-io.c:2084
 iomap_writepages+0x162/0x2d0 fs/iomap/buffered-io.c:2168
 xfs_vm_writepages+0x28a/0x300 fs/xfs/xfs_aops.c:701
 do_writepages+0x32e/0x550 mm/page-writeback.c:2598
 filemap_writeback mm/filemap.c:387 [inline]
 filemap_fdatawrite_range mm/filemap.c:412 [inline]
 file_write_and_wait_range+0x23e/0x340 mm/filemap.c:786
 xfs_file_fsync+0x195/0x800 fs/xfs/xfs_file.c:137
 generic_write_sync include/linux/fs.h:2639 [inline]
 xfs_file_buffered_write+0x723/0x8a0 fs/xfs/xfs_file.c:1015
 do_iter_readv_writev+0x623/0x8c0 fs/read_write.c:-1
 vfs_writev+0x31a/0x960 fs/read_write.c:1057
 do_pwritev fs/read_write.c:1153 [inline]
 __do_sys_pwritev2 fs/read_write.c:1211 [inline]
 __se_sys_pwritev2+0x179/0x290 fs/read_write.c:1202
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xfa/0xfa0 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f

The buggy address belongs to the object at ffff88816ced7c80
 which belongs to the cache kmalloc-96 of size 96
The buggy address is located 0 bytes to the right of
 allocated 80-byte region [ffff88816ced7c80, ffff88816ced7cd0)

The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x16ced7
flags: 0x57ff00000000000(node=1|zone=2|lastcpupid=0x7ff)
page_type: f5(slab)
raw: 057ff00000000000 ffff888100041280 dead000000000100 dead000000000122
raw: 0000000000000000 0000000080200020 00000000f5000000 0000000000000000
page dumped because: kasan: bad access detected
page_owner tracks the page as allocated
page last allocated via order 0, migratetype Unmovable, gfp_mask 0x252800(GFP_NOWAIT|__GFP_NORETRY|__GFP_COMP|__GFP_THISNODE), pid 1, tgid 1 (swapper/0), ts 12041529441, free_ts 0
 set_page_owner include/linux/page_owner.h:32 [inline]
 post_alloc_hook+0x240/0x2a0 mm/page_alloc.c:1851
 prep_new_page mm/page_alloc.c:1859 [inline]
 get_page_from_freelist+0x2365/0x2440 mm/page_alloc.c:3920
 __alloc_frozen_pages_noprof+0x181/0x370 mm/page_alloc.c:5209
 alloc_slab_page mm/slub.c:3086 [inline]
 allocate_slab+0x71/0x350 mm/slub.c:3257
 new_slab mm/slub.c:3311 [inline]
 ___slab_alloc+0xf56/0x1990 mm/slub.c:4671
 __slab_alloc+0x65/0x100 mm/slub.c:4794
 __slab_alloc_node mm/slub.c:4870 [inline]
 slab_alloc_node mm/slub.c:5266 [inline]
 __kmalloc_cache_node_noprof+0x4b7/0x6f0 mm/slub.c:5799
 kmalloc_node_noprof include/linux/slab.h:983 [inline]
 alloc_node_nr_active kernel/workqueue.c:4908 [inline]
 __alloc_workqueue+0x6a9/0x1b80 kernel/workqueue.c:5762
 alloc_workqueue_noprof+0xd4/0x210 kernel/workqueue.c:5822
 nbd_dev_add+0x4f1/0xae0 drivers/block/nbd.c:1961
 nbd_init+0x168/0x1f0 drivers/block/nbd.c:2691
 do_one_initcall+0x25a/0x860 init/main.c:1378
 do_initcall_level+0x104/0x190 init/main.c:1440
 do_initcalls+0x59/0xa0 init/main.c:1456
 kernel_init_freeable+0x334/0x4b0 init/main.c:1688
 kernel_init+0x1d/0x1d0 init/main.c:1578
page_owner free stack trace missing

Memory state around the buggy address:
 ffff88816ced7b80: 00 00 00 00 00 00 00 00 00 00 fc fc fc fc fc fc
 ffff88816ced7c00: 00 00 00 00 00 00 00 00 00 00 fc fc fc fc fc fc
>ffff88816ced7c80: 00 00 00 00 00 00 00 00 00 00 fc fc fc fc fc fc
                                                 ^
 ffff88816ced7d00: fa fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
 ffff88816ced7d80: 00 00 00 00 00 00 00 00 00 00 fc fc fc fc fc fc
==================================================================


***

If these findings have caused you to resend the series or submit a
separate fix, please add the following tag to your commit message:
  Tested-by: syzbot@syzkaller.appspotmail.com

---
This report is generated by a bot. It may contain errors.
syzbot ci engineers can be reached at syzkaller@googlegroups.com.

^ permalink raw reply

* Re: [PATCH] trace/pid_list: optimize pid_list->lock contention
From: Steven Rostedt @ 2025-11-12 15:42 UTC (permalink / raw)
  To: Yongliang Gao
  Cc: Sebastian Andrzej Siewior, mhiramat, mathieu.desnoyers,
	linux-kernel, linux-trace-kernel, Yongliang Gao, Huang Cun,
	frankjpliu
In-Reply-To: <CAJxhyqDCFRT_fPWHb67x-PUu+Om91UrbrQEifcF7m+dkZ35dqA@mail.gmail.com>

On Wed, 12 Nov 2025 13:27:10 +0800
Yongliang Gao <leonylgao@gmail.com> wrote:

> Thank you for your detailed response and the proposed RCU-like approach.
> 
> I've looked into using a regular seqlock instead of the current
> implementation, but as you pointed out, the write side is indeed a
> critical path. More importantly, I found that even with seqlock, the
> write_seqlock() function internally uses spin_lock() which on
> PREEMPT_RT gets converted to an mutex. This would cause the same
> issues we're trying to avoid - potential sleep in atomic contexts.

I believe there is a raw_read_seqcount() functionality that is safe for
PREEMPT_RT. Have you looked into using that?

-- Steve

^ permalink raw reply


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