* [PATCH] ring-buffer: Mark concurrent accesses to waiter flags
@ 2026-11-11 8:41 Zhu Jun
2026-11-12 10:45 ` Steven Rostedt
0 siblings, 1 reply; 2+ messages in thread
From: Zhu Jun @ 2026-11-11 8:41 UTC (permalink / raw)
To: rostedt
Cc: vdonnefort, mhiramat, mathieu.desnoyers, linux-trace-kernel,
linux-kernel, syzbot+53ab168fdda7fba508ba, Zhu Jun
Poll and wait paths set the pending waiter flags while ring buffer
writers test and clear them without a common lock. The irq_work callback
also accesses the full-buffer wakeup flags concurrently. These plain
accesses cause KCSAN reports.
Use READ_ONCE() and WRITE_ONCE() for the shared waiter and wakeup flags.
Keep the existing barriers and irq_work wakeup protocol unchanged.
Fixes: 15693458c4bc ("tracing/ring-buffer: Move poll wake ups into ring buffer code")
Fixes: 1e0d6714aceb ("ring-buffer: Do not wake up a splice waiter when page is not full")
Signed-off-by: Zhu Jun <zhujun2@cmss.chinamobile.com>
---
kernel/trace/ring_buffer.c | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 75cd8df23c1b..18f023cf1d6f 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -904,14 +904,14 @@ static void rb_wake_up_waiters(struct irq_work *work)
(void)atomic_fetch_inc_release(&rbwork->seq);
wake_up_all(&rbwork->waiters);
- if (rbwork->full_waiters_pending || rbwork->wakeup_full) {
+ if (READ_ONCE(rbwork->full_waiters_pending) || READ_ONCE(rbwork->wakeup_full)) {
/* Only cpu_buffer sets the above flags */
struct ring_buffer_per_cpu *cpu_buffer =
container_of(rbwork, struct ring_buffer_per_cpu, irq_work);
scoped_guard(raw_spinlock_irqsave, &cpu_buffer->reader_lock) {
- rbwork->wakeup_full = false;
- rbwork->full_waiters_pending = false;
+ WRITE_ONCE(rbwork->wakeup_full, false);
+ WRITE_ONCE(rbwork->full_waiters_pending, false);
/* Waking up all waiters, they will reset the shortest full */
cpu_buffer->shortest_full = 0;
@@ -1023,9 +1023,9 @@ rb_wait_cond(struct rb_irq_work *rbwork, struct trace_buffer *buffer,
* a task has been queued. It's OK for spurious wake ups.
*/
if (full)
- rbwork->full_waiters_pending = true;
+ WRITE_ONCE(rbwork->full_waiters_pending, true);
else
- rbwork->waiters_pending = true;
+ WRITE_ONCE(rbwork->waiters_pending, true);
return false;
}
@@ -1153,12 +1153,12 @@ __poll_t ring_buffer_poll_wait(struct trace_buffer *buffer, int cpu,
* full_waiters_pending doesn't leak up into the above.
*/
smp_mb();
- rbwork->full_waiters_pending = true;
+ WRITE_ONCE(rbwork->full_waiters_pending, true);
return 0;
}
poll_wait(filp, &rbwork->waiters, poll_table);
- rbwork->waiters_pending = true;
+ WRITE_ONCE(rbwork->waiters_pending, true);
/*
* There's a tight race between setting the waiters_pending and
@@ -4378,14 +4378,14 @@ rb_irq_work_queue(struct rb_irq_work *irq_work)
static __always_inline void
rb_wakeups(struct trace_buffer *buffer, struct ring_buffer_per_cpu *cpu_buffer)
{
- if (buffer->irq_work.waiters_pending) {
- buffer->irq_work.waiters_pending = false;
+ if (READ_ONCE(buffer->irq_work.waiters_pending)) {
+ WRITE_ONCE(buffer->irq_work.waiters_pending, false);
/* irq_work_queue() supplies it's own memory barriers */
rb_irq_work_queue(&buffer->irq_work);
}
- if (cpu_buffer->irq_work.waiters_pending) {
- cpu_buffer->irq_work.waiters_pending = false;
+ if (READ_ONCE(cpu_buffer->irq_work.waiters_pending)) {
+ WRITE_ONCE(cpu_buffer->irq_work.waiters_pending, false);
/* irq_work_queue() supplies it's own memory barriers */
rb_irq_work_queue(&cpu_buffer->irq_work);
}
@@ -4396,7 +4396,7 @@ rb_wakeups(struct trace_buffer *buffer, struct ring_buffer_per_cpu *cpu_buffer)
if (cpu_buffer->reader_page == cpu_buffer->commit_page)
return;
- if (!cpu_buffer->irq_work.full_waiters_pending)
+ if (!READ_ONCE(cpu_buffer->irq_work.full_waiters_pending))
return;
cpu_buffer->last_pages_touch = local_read(&cpu_buffer->pages_touched);
@@ -4404,8 +4404,8 @@ rb_wakeups(struct trace_buffer *buffer, struct ring_buffer_per_cpu *cpu_buffer)
if (!full_hit(buffer, cpu_buffer->cpu, cpu_buffer->shortest_full))
return;
- cpu_buffer->irq_work.wakeup_full = true;
- cpu_buffer->irq_work.full_waiters_pending = false;
+ WRITE_ONCE(cpu_buffer->irq_work.wakeup_full, true);
+ WRITE_ONCE(cpu_buffer->irq_work.full_waiters_pending, false);
/* irq_work_queue() supplies it's own memory barriers */
rb_irq_work_queue(&cpu_buffer->irq_work);
}
--
2.51.0
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] ring-buffer: Mark concurrent accesses to waiter flags
2026-11-11 8:41 [PATCH] ring-buffer: Mark concurrent accesses to waiter flags Zhu Jun
@ 2026-11-12 10:45 ` Steven Rostedt
0 siblings, 0 replies; 2+ messages in thread
From: Steven Rostedt @ 2026-11-12 10:45 UTC (permalink / raw)
To: Zhu Jun
Cc: vdonnefort, mhiramat, mathieu.desnoyers, linux-trace-kernel,
linux-kernel, syzbot+53ab168fdda7fba508ba
On Wed, 11 Nov 2026 16:41:37 +0800
Zhu Jun <zhujun2@cmss.chinamobile.com> wrote:
> Poll and wait paths set the pending waiter flags while ring buffer
> writers test and clear them without a common lock. The irq_work callback
> also accesses the full-buffer wakeup flags concurrently. These plain
> accesses cause KCSAN reports.
>
> Use READ_ONCE() and WRITE_ONCE() for the shared waiter and wakeup flags.
> Keep the existing barriers and irq_work wakeup protocol unchanged.
>
> Fixes: 15693458c4bc ("tracing/ring-buffer: Move poll wake ups into ring buffer code")
> Fixes: 1e0d6714aceb ("ring-buffer: Do not wake up a splice waiter when page is not full")
> Signed-off-by: Zhu Jun <zhujun2@cmss.chinamobile.com>
Is this simply to prevent read/write tearing?
-- Steve
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-11-12 10:46 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-11 8:41 [PATCH] ring-buffer: Mark concurrent accesses to waiter flags Zhu Jun
2026-11-12 10:45 ` Steven Rostedt
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®