tracing: Fix remote reader page swap failures
Subsystems (3)
v2 cover tracing: Fix remote reader page swap failures
The simple ring buffer's reader-page swap retry loop mishandles its last attempt. A success at that point is reported as an error, while a failure is allowed to continue into the pointer updates. The remote ring buffer consumer compounds callback failures by warning and continuing with stale reader metadata.
Fix the retry result in the provider, then stop the remote consumer before it mutates its local page list when the swap fails.
These paths are used by remote tracing, including arm64 nVHE EL2 tracing and CONFIG_TRACE_REMOTE_TEST.
Testing:
make C=2 W=1 kernel/trace/simple_ring_buffer.o kernel/trace/ring_buffer.o scripts/checkpatch.pl --no-tree (each formatted patch)
No runtime reproducer was run. The two final-attempt outcomes follow from the retry counter's post-decrement semantics. An arm64 cross-compiler was not available.
---
Changes in v2:
- Report callback failures with pr_warn_ratelimited() instead of WARN_ON_ONCE(), as suggested by Vincent Donnefort.
- Add Vincent Donnefort's Reviewed-by tag to patch 1.
- Link to v1: https://lore.kernel.org/r/[email protected]
---
Ivan Immanuel Shaji (2):
tracing: Fix retry exhaustion in simple ring buffer reader swap
ring-buffer: Stop remote reader update when page swap fails
kernel/trace/ring_buffer.c | 7 +++++-- kernel/trace/simple_ring_buffer.c | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-)
---
base-commit: 66498c75b4f8017f62d720d9b59675bdf3abce91
change-id: 20260825-kernel-patch-1-d806e3de01a5
Best regards,
Signature · 1 line
Ivan Immanuel Shaji <[email protected]>
PATCH v2 1/2 tracing: Fix retry exhaustion in simple ring buffer reader swap
simple_ring_buffer_swap_reader_page() starts with retry set to 8 and post-decrements it only after a failed link replacement. On the final attempt, a successful replacement leaves retry at zero, while a failed replacement leaves it at -1.
The current !retry test reverses both outcomes. It returns an error after a successful final replacement, leaving the link update complete but the reader bookkeeping unfinished. After a failed final replacement, it falls through and updates the head and reader pointers as though the replacement succeeded, which can corrupt the ring.
Treat only a negative counter as exhaustion and return the documented -EBUSY error.
--- kernel/trace/simple_ring_buffer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
kernel/trace/simple_ring_buffer.c +2 -2
@@ -160,8 +160,8 @@ int simple_ring_buffer_swap_reader_page(struct simple_rb_per_cpu *cpu_buffer) overrun = cpu_buffer->meta->overrun; }while (!simple_bpage_unset_head_link (last, reader,SIMPLE_RB_LINK_NORMAL ) && retry--); -if (!retry) -return -EINVAL ; +if (retry <0 ) +return -EBUSY ; cpu_buffer->head_page =simple_bpage_from_link (reader->link.next); cpu_buffer->head_page->link.prev = &reader->link;
Signature · 1 line
2.53.0
PATCH v2 2/2 ring-buffer: Stop remote reader update when page swap fails
In reply to Ivan Immanuel ShajiThe remote swap_reader_page callback can return -EBUSY when the writer moves the head before the remote catches it, particularly during an event storm on a small buffer. __rb_get_reader_page_from_remote() currently warns about that failure but continues with the unchanged reader ID and rearranges the local page list as though the swap succeeded.
Handle the callback failure as a recoverable error. Report it with pr_warn_ratelimited() and return NULL. Callers already handle a NULL reader page as a failed attempt. This avoids splicing the same page as both the previous and new reader without flooding the log under contention.
--- kernel/trace/ring_buffer.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
kernel/trace/ring_buffer.c +5 -2
@@ -5805,8 +5805,11 @@ __rb_get_reader_page_from_remote(struct ring_buffer_per_cpu *cpu_buffer) prev_reader = cpu_buffer->subbuf_ids[cpu_buffer->meta_page->reader.id]; -WARN_ON_ONCE (cpu_buffer->remote->swap_reader_page (cpu_buffer->cpu, - cpu_buffer->remote->priv)); +if (cpu_buffer->remote->swap_reader_page (cpu_buffer->cpu, + cpu_buffer->remote->priv)) { +pr_warn_ratelimited ("Remote reader page swap failed\n" ); +return NULL ; + }/* nr_pages doesn't include the reader page */ if (WARN_ON_ONCE (cpu_buffer->meta_page->reader.id > cpu_buffer->nr_pages))return NULL ;
Signature · 1 line
2.53.0