The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH 0/6] ring-buffer: Fixes for subbuf resizing and persistent buffers
@ 2026-08-06 21:13 Vincent Donnefort
  2026-08-06 21:13 ` [PATCH 1/6] ring-buffer: Prevent resizing of persistent ring buffer Vincent Donnefort
                   ` (5 more replies)
  0 siblings, 6 replies; 15+ messages in thread
From: Vincent Donnefort @ 2026-08-06 21:13 UTC (permalink / raw)
  To: rostedt, mhiramat, linux-trace-kernel
  Cc: mathieu.desnoyers, kernel-team, linux-kernel, Vincent Donnefort

This series addresses multiple issues discovered with the dynamic ring
buffer resizing.

Changelog:

v2:

  - Prevent resizing of the persistent ring buffer
  - Add missing bpage::order init
  - Rework subbuf_size/subbuf_order (Sashiko)
  - Remove ring_buffer_per_cpu::mapped
  - Dynamically calculate trace_buffer::max_data_size

v1 (https://lore.kernel.org/all/20260805153225.2096152-1-vdonnefort@google.com/

Vincent Donnefort (6):
  ring-buffer: Prevent resizing of persistent ring buffer
  ring-buffer: Prevent subbuf order change when resizing is disabled
  ring-buffer: Initialise reader page order in rb_allocate_cpu_buffer()
  ring-buffer: Fix subbuf resize concurrency
  ring-buffer: Dynamically calculate max_data_size
  ring-buffer: Remove ring_buffer_per_cpu::mapped

 kernel/trace/ring_buffer.c | 216 ++++++++++++++++++++-----------------
 1 file changed, 117 insertions(+), 99 deletions(-)


base-commit: 075b74841bd0065a3bda3440873c747938e69b68
-- 
2.55.0.654.g21b8a5bc05-goog


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

* [PATCH 1/6] ring-buffer: Prevent resizing of persistent ring buffer
  2026-08-06 21:13 [PATCH 0/6] ring-buffer: Fixes for subbuf resizing and persistent buffers Vincent Donnefort
@ 2026-08-06 21:13 ` Vincent Donnefort
  2026-08-07  2:18   ` Masami Hiramatsu
  2026-08-06 21:13 ` [PATCH 2/6] ring-buffer: Prevent subbuf order change when resizing is disabled Vincent Donnefort
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 15+ messages in thread
From: Vincent Donnefort @ 2026-08-06 21:13 UTC (permalink / raw)
  To: rostedt, mhiramat, linux-trace-kernel
  Cc: mathieu.desnoyers, kernel-team, linux-kernel, Vincent Donnefort

Dynamically resizing a persistent ring buffer is not possible. Disable
the feature.

Fixes: be68d63a139b ("ring-buffer: Add ring_buffer_alloc_range()")
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>

diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 8e2485bb3aa8..afe75ad2bbf2 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -2528,6 +2528,8 @@ rb_allocate_cpu_buffer(struct trace_buffer *buffer, long nr_pages, int cpu)
 		if (cpu_buffer->ring_meta->head_buffer)
 			rb_meta_buffer_update(cpu_buffer, bpage);
 		bpage->range = 1;
+
+		atomic_inc(&cpu_buffer->resize_disabled);
 	} else if (buffer->remote) {
 		struct ring_buffer_desc *desc = ring_buffer_desc(buffer->remote->desc, cpu);
 
-- 
2.55.0.654.g21b8a5bc05-goog


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

* [PATCH 2/6] ring-buffer: Prevent subbuf order change when resizing is disabled
  2026-08-06 21:13 [PATCH 0/6] ring-buffer: Fixes for subbuf resizing and persistent buffers Vincent Donnefort
  2026-08-06 21:13 ` [PATCH 1/6] ring-buffer: Prevent resizing of persistent ring buffer Vincent Donnefort
@ 2026-08-06 21:13 ` Vincent Donnefort
  2026-08-06 21:13 ` [PATCH 3/6] ring-buffer: Initialise reader page order in rb_allocate_cpu_buffer() Vincent Donnefort
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 15+ messages in thread
From: Vincent Donnefort @ 2026-08-06 21:13 UTC (permalink / raw)
  To: rostedt, mhiramat, linux-trace-kernel
  Cc: mathieu.desnoyers, kernel-team, linux-kernel, Vincent Donnefort,
	syzbot+e0cc44465d6bae735679

Because ring_buffer_subbuf_order_set() frees buffer pages, we can't
allow it when resizing is disabled. A non-consuming reader is at risk of
use-after-free (rb_advance_iter()).

Return -EBUSY on resize_disabled, matching ring_buffer_resize()
behaviour.

Fixes: f9b94daa542a ("ring-buffer: Set new size of the ring buffer sub page")
Reported-by: syzbot+e0cc44465d6bae735679@syzkaller.appspotmail.com
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>

diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index afe75ad2bbf2..9bc467c4dbbb 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -7360,7 +7360,7 @@ int ring_buffer_subbuf_order_set(struct trace_buffer *buffer, int order)
 
 		cpu_buffer = buffer->buffers[cpu];
 
-		if (cpu_buffer->mapped) {
+		if (atomic_read(&cpu_buffer->resize_disabled)) {
 			err = -EBUSY;
 			goto error;
 		}
-- 
2.55.0.654.g21b8a5bc05-goog


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

* [PATCH 3/6] ring-buffer: Initialise reader page order in rb_allocate_cpu_buffer()
  2026-08-06 21:13 [PATCH 0/6] ring-buffer: Fixes for subbuf resizing and persistent buffers Vincent Donnefort
  2026-08-06 21:13 ` [PATCH 1/6] ring-buffer: Prevent resizing of persistent ring buffer Vincent Donnefort
  2026-08-06 21:13 ` [PATCH 2/6] ring-buffer: Prevent subbuf order change when resizing is disabled Vincent Donnefort
@ 2026-08-06 21:13 ` Vincent Donnefort
  2026-08-06 21:13 ` [PATCH 4/6] ring-buffer: Fix subbuf resize concurrency Vincent Donnefort
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 15+ messages in thread
From: Vincent Donnefort @ 2026-08-06 21:13 UTC (permalink / raw)
  To: rostedt, mhiramat, linux-trace-kernel
  Cc: mathieu.desnoyers, kernel-team, linux-kernel, Vincent Donnefort

In rb_allocate_cpu_buffer(), bpage->order was omitted, leaving it as 0.
This is an issue for a ring-buffer with subbufs bigger than PAGE_SIZE if
when freed: free_buffer_page() relies on this value. Align the value
with the actual allocation size (buffer::subbuf_order).

Fixes: f9b94daa542a ("ring-buffer: Set new size of the ring buffer sub page")
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>

diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 9bc467c4dbbb..4747cf427575 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -2510,6 +2510,7 @@ rb_allocate_cpu_buffer(struct trace_buffer *buffer, long nr_pages, int cpu)
 	bpage = alloc_cpu_page(cpu);
 	if (!bpage)
 		return NULL;
+	bpage->order = cpu_buffer->buffer->subbuf_order;
 
 	rb_check_bpage(cpu_buffer, bpage);
 
-- 
2.55.0.654.g21b8a5bc05-goog


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

* [PATCH 4/6] ring-buffer: Fix subbuf resize concurrency
  2026-08-06 21:13 [PATCH 0/6] ring-buffer: Fixes for subbuf resizing and persistent buffers Vincent Donnefort
                   ` (2 preceding siblings ...)
  2026-08-06 21:13 ` [PATCH 3/6] ring-buffer: Initialise reader page order in rb_allocate_cpu_buffer() Vincent Donnefort
@ 2026-08-06 21:13 ` Vincent Donnefort
  2026-08-06 21:13 ` [PATCH 5/6] ring-buffer: Dynamically calculate max_data_size Vincent Donnefort
  2026-08-06 21:13 ` [PATCH 6/6] ring-buffer: Remove ring_buffer_per_cpu::mapped Vincent Donnefort
  5 siblings, 0 replies; 15+ messages in thread
From: Vincent Donnefort @ 2026-08-06 21:13 UTC (permalink / raw)
  To: rostedt, mhiramat, linux-trace-kernel
  Cc: mathieu.desnoyers, kernel-team, linux-kernel, Vincent Donnefort,
	Sashiko

trace_buffer subbuf_size is read lockless in ring_buffer_read_page() and
ring_buffer_read_start(), while it can simultaneously be resized with
ring_buffer_subbuf_order_set().

Instead of trace_buffer::subbuf_size, use bpage::order in
ring_buffer_read_start() and ring_buffer_read_page().

In ring_buffer_read_start(), even with resize_disabled, there is still a
possibility of a race with a buffer modification. Hold the trace_buffer
mutex to synchronise with any pending ring buffer order modification.

trace_buffer::subbuf_size is now actually useless, remove it. Also,
create accessors rb_subbuf_capacity() and rb_page_capacity() which
return the actual size available for storing events, while
rb_subbuf_size() returns the actual subbuf page-size.

Reported-by: Sashiko <sashiko-bot@kernel.org>
Fixes: f9b94daa542a ("ring-buffer: Set new size of the ring buffer sub page")
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>

diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 4747cf427575..3531005aab43 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -586,11 +586,25 @@ struct trace_buffer {
 
 	struct ring_buffer_meta		*meta;
 
-	unsigned int			subbuf_size;
 	unsigned int			subbuf_order;
 	unsigned int			max_data_size;
 };
 
+static inline unsigned int rb_subbuf_size(struct trace_buffer *buffer)
+{
+	return PAGE_SIZE << buffer->subbuf_order;
+}
+
+static inline unsigned int rb_subbuf_capacity(struct trace_buffer *buffer)
+{
+	return rb_subbuf_size(buffer) - BUF_PAGE_HDR_SIZE;
+}
+
+static inline unsigned int rb_page_capacity(struct buffer_page *bpage)
+{
+	return (PAGE_SIZE << bpage->order) - BUF_PAGE_HDR_SIZE;
+}
+
 struct ring_buffer_iter {
 	struct ring_buffer_per_cpu	*cpu_buffer;
 	unsigned long			head;
@@ -630,7 +644,7 @@ int ring_buffer_print_page_header(struct trace_buffer *buffer, struct trace_seq
 	trace_seq_printf(s, "\tfield: char data;\t"
 			 "offset:%u;\tsize:%u;\tsigned:%u;\n",
 			 (unsigned int)offsetof(typeof(field), data),
-			 (unsigned int)(buffer ? buffer->subbuf_size :
+			 (unsigned int)(buffer ? rb_subbuf_capacity(buffer) :
 						 PAGE_SIZE - BUF_PAGE_HDR_SIZE),
 			 (unsigned int)is_signed_type(char));
 
@@ -1620,7 +1634,7 @@ rb_range_align_subbuf(unsigned long addr, int subbuf_size, int nr_subbufs)
  */
 static void *rb_range_meta(struct trace_buffer *buffer, int nr_pages, int cpu)
 {
-	int subbuf_size = buffer->subbuf_size + BUF_PAGE_HDR_SIZE;
+	int subbuf_size = rb_subbuf_size(buffer);
 	struct ring_buffer_cpu_meta *meta;
 	struct ring_buffer_meta *bmeta;
 	unsigned long ptr;
@@ -2432,8 +2446,8 @@ static int __rb_allocate_pages(struct ring_buffer_per_cpu *cpu_buffer,
 			bpage->id = i + 1;
 			cpu_buffer->subbuf_ids[i + 1] = bpage;
 		} else {
-			int order = cpu_buffer->buffer->subbuf_order;
-			bpage->page = alloc_cpu_data(cpu_buffer->cpu, order);
+			bpage->page = alloc_cpu_data(cpu_buffer->cpu,
+						     cpu_buffer->buffer->subbuf_order);
 			if (!bpage->page)
 				goto free_pages;
 		}
@@ -2556,8 +2570,7 @@ rb_allocate_cpu_buffer(struct trace_buffer *buffer, long nr_pages, int cpu)
 		bpage->range = 1;
 		cpu_buffer->subbuf_ids[0] = bpage;
 	} else {
-		int order = cpu_buffer->buffer->subbuf_order;
-		bpage->page = alloc_cpu_data(cpu, order);
+		bpage->page = alloc_cpu_data(cpu, bpage->order);
 		if (!bpage->page)
 			goto fail_free_reader;
 	}
@@ -2731,10 +2744,9 @@ static struct trace_buffer *alloc_buffer(unsigned long size, unsigned flags,
 
 	buffer->subbuf_order = order;
 	subbuf_size = (PAGE_SIZE << order);
-	buffer->subbuf_size = subbuf_size - BUF_PAGE_HDR_SIZE;
 
 	/* Max payload is buffer page size - header (8bytes) */
-	buffer->max_data_size = buffer->subbuf_size - (sizeof(u32) * 2);
+	buffer->max_data_size = rb_subbuf_capacity(buffer) - (sizeof(u32) * 2);
 
 	buffer->flags = flags;
 	buffer->clock = trace_clock_local;
@@ -2818,9 +2830,8 @@ static struct trace_buffer *alloc_buffer(unsigned long size, unsigned flags,
 		if (nr_pages < 2)
 			goto fail_free_buffers;
 	} else {
-
 		/* need at least two pages */
-		nr_pages = DIV_ROUND_UP(size, buffer->subbuf_size);
+		nr_pages = DIV_ROUND_UP(size, rb_subbuf_capacity(buffer));
 		if (nr_pages < 2)
 			nr_pages = 2;
 	}
@@ -3203,7 +3214,7 @@ static void update_pages_handler(struct work_struct *work)
  * @size: the new size.
  * @cpu_id: the cpu buffer to resize
  *
- * Minimum size is 2 * buffer->subbuf_size.
+ * Minimum size is 2 * rb_subbuf_capacity(buffer).
  *
  * Returns 0 on success and < 0 on failure.
  */
@@ -3225,12 +3236,6 @@ int ring_buffer_resize(struct trace_buffer *buffer, unsigned long size,
 	    !cpumask_test_cpu(cpu_id, buffer->cpumask))
 		return 0;
 
-	nr_pages = DIV_ROUND_UP(size, buffer->subbuf_size);
-
-	/* we need a minimum of two pages */
-	if (nr_pages < 2)
-		nr_pages = 2;
-
 	/*
 	 * Keep CPUs from coming online while resizing to synchronize
 	 * with new per CPU buffers being created.
@@ -3241,6 +3246,12 @@ int ring_buffer_resize(struct trace_buffer *buffer, unsigned long size,
 	mutex_lock(&buffer->mutex);
 	atomic_inc(&buffer->resizing);
 
+	nr_pages = DIV_ROUND_UP(size, rb_subbuf_capacity(buffer));
+
+	/* we need a minimum of two pages */
+	if (nr_pages < 2)
+		nr_pages = 2;
+
 	if (cpu_id == RING_BUFFER_ALL_CPUS) {
 		/*
 		 * Don't succeed if resizing is disabled, as a reader might be
@@ -3513,7 +3524,7 @@ rb_event_index(struct ring_buffer_per_cpu *cpu_buffer, struct ring_buffer_event
 {
 	unsigned long addr = (unsigned long)event;
 
-	addr &= (PAGE_SIZE << cpu_buffer->buffer->subbuf_order) - 1;
+	addr &= rb_subbuf_size(cpu_buffer->buffer) - 1;
 
 	return addr - BUF_PAGE_HDR_SIZE;
 }
@@ -3755,8 +3766,8 @@ static inline void
 rb_reset_tail(struct ring_buffer_per_cpu *cpu_buffer,
 	      unsigned long tail, struct rb_event_info *info)
 {
-	unsigned long bsize = READ_ONCE(cpu_buffer->buffer->subbuf_size);
 	struct buffer_page *tail_page = info->tail_page;
+	unsigned long bsize = rb_page_capacity(tail_page);
 	struct ring_buffer_event *event;
 	unsigned long length = info->length;
 
@@ -4102,7 +4113,7 @@ rb_try_to_discard(struct ring_buffer_per_cpu *cpu_buffer,
 	new_index = rb_event_index(cpu_buffer, event);
 	old_index = new_index + rb_event_ts_length(event);
 	addr = (unsigned long)event;
-	addr &= ~((PAGE_SIZE << cpu_buffer->buffer->subbuf_order) - 1);
+	addr &= ~(rb_subbuf_size(cpu_buffer->buffer) - 1);
 
 	bpage = READ_ONCE(cpu_buffer->tail_page);
 
@@ -4767,7 +4778,7 @@ __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer,
 	tail = write - info->length;
 
 	/* See if we shot pass the end of this buffer page */
-	if (unlikely(write > cpu_buffer->buffer->subbuf_size)) {
+	if (unlikely(write > rb_page_capacity(tail_page))) {
 		check_buffer(cpu_buffer, info, CHECK_FULL_PAGE);
 		return rb_move_tail(cpu_buffer, tail, info);
 	}
@@ -5012,7 +5023,7 @@ rb_decrement_entry(struct ring_buffer_per_cpu *cpu_buffer,
 	struct buffer_page *bpage = cpu_buffer->commit_page;
 	struct buffer_page *start;
 
-	addr &= ~((PAGE_SIZE << cpu_buffer->buffer->subbuf_order) - 1);
+	addr &= ~(rb_subbuf_size(cpu_buffer->buffer) - 1);
 
 	/* Do the likely case first */
 	if (likely(bpage->page == (void *)addr)) {
@@ -5799,7 +5810,6 @@ static struct buffer_page *
 __rb_get_reader_page(struct ring_buffer_per_cpu *cpu_buffer)
 {
 	int max_loops = cpu_buffer->ring_meta ? cpu_buffer->nr_pages : 3;
-	unsigned long bsize = READ_ONCE(cpu_buffer->buffer->subbuf_size);
 	struct buffer_page *reader = NULL;
 	unsigned long overwrite;
 	unsigned long flags;
@@ -5947,7 +5957,7 @@ __rb_get_reader_page(struct ring_buffer_per_cpu *cpu_buffer)
 #define USECS_WAIT	1000000
         for (nr_loops = 0; nr_loops < USECS_WAIT; nr_loops++) {
 		/* If the write is past the end of page, a writer is still updating it */
-		if (likely(!reader || rb_page_write(reader) <= bsize))
+		if (likely(!reader || rb_page_write(reader) <= rb_page_capacity(reader)))
 			break;
 
 		udelay(1);
@@ -6380,36 +6390,44 @@ EXPORT_SYMBOL_GPL(ring_buffer_consume);
 struct ring_buffer_iter *
 ring_buffer_read_start(struct trace_buffer *buffer, int cpu, gfp_t flags)
 {
+	struct ring_buffer_iter *iter __free(kfree) = kzalloc_obj(*iter, flags);
 	struct ring_buffer_per_cpu *cpu_buffer;
-	struct ring_buffer_iter *iter;
+
+	if (!iter)
+		return NULL;
 
 	if (!cpumask_test_cpu(cpu, buffer->cpumask))
 		return NULL;
 
-	iter = kzalloc_obj(*iter, flags);
-	if (!iter)
-		return NULL;
-
-	/* Holds the entire event: data and meta data */
-	iter->event_size = buffer->subbuf_size;
-	iter->event = kmalloc(iter->event_size, flags);
-	if (!iter->event) {
-		kfree(iter);
-		return NULL;
-	}
-
 	cpu_buffer = buffer->buffers[cpu];
 
-	iter->cpu_buffer = cpu_buffer;
+	/*
+	 * Only KDB is using GFP_ATOMIC, for the others, lock the buffer to
+	 * prevent concurrent resizing.
+	 */
+	if (gfpflags_allow_blocking(flags))
+		mutex_lock(&buffer->mutex);
 
 	atomic_inc(&cpu_buffer->resize_disabled);
 
+	if (gfpflags_allow_blocking(flags))
+		mutex_unlock(&buffer->mutex);
+
+	/* Holds the entire event: data and meta data. */
+	iter->event_size = rb_page_capacity(READ_ONCE(cpu_buffer->reader_page));
+	iter->event = kmalloc(iter->event_size, flags);
+	if (!iter->event) {
+		atomic_dec(&cpu_buffer->resize_disabled);
+		return NULL;
+	}
+	iter->cpu_buffer = cpu_buffer;
+
 	guard(raw_spinlock_irqsave)(&cpu_buffer->reader_lock);
 	arch_spin_lock(&cpu_buffer->lock);
 	rb_iter_reset(iter);
 	arch_spin_unlock(&cpu_buffer->lock);
 
-	return iter;
+	return_ptr(iter);
 }
 EXPORT_SYMBOL_GPL(ring_buffer_read_start);
 
@@ -6463,7 +6481,7 @@ unsigned long ring_buffer_size(struct trace_buffer *buffer, int cpu)
 	if (!cpumask_test_cpu(cpu, buffer->cpumask))
 		return 0;
 
-	return buffer->subbuf_size * buffer->buffers[cpu]->nr_pages;
+	return rb_subbuf_capacity(buffer) * buffer->buffers[cpu]->nr_pages;
 }
 EXPORT_SYMBOL_GPL(ring_buffer_size);
 
@@ -7094,15 +7112,15 @@ int ring_buffer_read_page(struct trace_buffer *buffer,
 	if (!data_page || !data_page->data)
 		return -1;
 
-	if (data_page->order != buffer->subbuf_order)
-		return -1;
-
 	dpage = data_page->data;
 	if (!dpage)
 		return -1;
 
 	guard(raw_spinlock_irqsave)(&cpu_buffer->reader_lock);
 
+	if (data_page->order != cpu_buffer->reader_page->order)
+		return -1;
+
 	reader = rb_get_reader_page(cpu_buffer);
 	if (!reader)
 		return -1;
@@ -7228,7 +7246,7 @@ int ring_buffer_read_page(struct trace_buffer *buffer,
 		 * missed events, then record it there.
 		 */
 		if (missed_events > 0 &&
-		    buffer->subbuf_size - size >= sizeof(missed_events)) {
+		    rb_page_capacity(reader) - size >= sizeof(missed_events)) {
 			memcpy(&dpage->data[size], &missed_events,
 			       sizeof(missed_events));
 			local_add(RB_MISSED_STORED, &dpage->commit);
@@ -7248,8 +7266,8 @@ int ring_buffer_read_page(struct trace_buffer *buffer,
 	/*
 	 * This page may be off to user land. Zero it out here.
 	 */
-	if (size < buffer->subbuf_size)
-		memset(&dpage->data[size], 0, buffer->subbuf_size - size);
+	if (size < rb_page_capacity(reader))
+		memset(&dpage->data[size], 0, rb_page_capacity(reader) - size);
 
 	return read;
 }
@@ -7275,7 +7293,7 @@ EXPORT_SYMBOL_GPL(ring_buffer_read_page_data);
  */
 int ring_buffer_subbuf_size_get(struct trace_buffer *buffer)
 {
-	return buffer->subbuf_size + BUF_PAGE_HDR_SIZE;
+	return rb_subbuf_size(buffer);
 }
 EXPORT_SYMBOL_GPL(ring_buffer_subbuf_size_get);
 
@@ -7320,7 +7338,8 @@ int ring_buffer_subbuf_order_set(struct trace_buffer *buffer, int order)
 {
 	struct ring_buffer_per_cpu *cpu_buffer;
 	struct buffer_page *bpage, *tmp;
-	int old_order, old_size;
+	unsigned int old_capacity;
+	int old_order;
 	int nr_pages;
 	int psize;
 	int err;
@@ -7329,9 +7348,6 @@ int ring_buffer_subbuf_order_set(struct trace_buffer *buffer, int order)
 	if (!buffer || order < 0)
 		return -EINVAL;
 
-	if (buffer->subbuf_order == order)
-		return 0;
-
 	psize = (1 << order) * PAGE_SIZE;
 	if (psize <= BUF_PAGE_HDR_SIZE)
 		return -EINVAL;
@@ -7340,18 +7356,21 @@ int ring_buffer_subbuf_order_set(struct trace_buffer *buffer, int order)
 	if (psize > RB_WRITE_MASK + 1)
 		return -EINVAL;
 
-	old_order = buffer->subbuf_order;
-	old_size = buffer->subbuf_size;
-
 	/* prevent another thread from changing buffer sizes */
 	guard(mutex)(&buffer->mutex);
+
+	old_order = buffer->subbuf_order;
+	if (old_order == order)
+		return 0;
+
+	old_capacity = (PAGE_SIZE << old_order) - BUF_PAGE_HDR_SIZE;
+
 	atomic_inc(&buffer->record_disabled);
 
 	/* Make sure all commits have finished */
 	synchronize_rcu();
 
 	buffer->subbuf_order = order;
-	buffer->subbuf_size = psize - BUF_PAGE_HDR_SIZE;
 
 	/* Make sure all new buffers are allocated, before deleting the old ones */
 	for_each_buffer_cpu(buffer, cpu) {
@@ -7367,8 +7386,8 @@ int ring_buffer_subbuf_order_set(struct trace_buffer *buffer, int order)
 		}
 
 		/* Update the number of pages to match the new size */
-		nr_pages = old_size * buffer->buffers[cpu]->nr_pages;
-		nr_pages = DIV_ROUND_UP(nr_pages, buffer->subbuf_size);
+		nr_pages = old_capacity * buffer->buffers[cpu]->nr_pages;
+		nr_pages = DIV_ROUND_UP(nr_pages, rb_subbuf_capacity(buffer));
 
 		/* we need a minimum of two pages */
 		if (nr_pages < 2)
@@ -7454,7 +7473,6 @@ int ring_buffer_subbuf_order_set(struct trace_buffer *buffer, int order)
 
 error:
 	buffer->subbuf_order = old_order;
-	buffer->subbuf_size = old_size;
 
 	atomic_dec(&buffer->record_disabled);
 
@@ -7532,7 +7550,7 @@ static void rb_setup_ids_meta_page(struct ring_buffer_per_cpu *cpu_buffer,
 
 	meta->meta_struct_len = sizeof(*meta);
 	meta->nr_subbufs = nr_subbufs;
-	meta->subbuf_size = cpu_buffer->buffer->subbuf_size + BUF_PAGE_HDR_SIZE;
+	meta->subbuf_size = rb_subbuf_size(cpu_buffer->buffer);
 	meta->meta_page_size = meta->subbuf_size;
 
 	rb_update_meta_page(cpu_buffer);
@@ -7894,7 +7912,7 @@ int ring_buffer_map_get_reader(struct trace_buffer *buffer, int cpu)
 			 * missed events, then record it there.
 			 */
 			commit = rb_page_size(reader);
-			if (buffer->subbuf_size - commit >= sizeof(missed_events)) {
+			if (rb_subbuf_capacity(buffer) - commit >= sizeof(missed_events)) {
 				memcpy(&dpage->data[commit], &missed_events,
 				       sizeof(missed_events));
 				local_add(RB_MISSED_STORED, &dpage->commit);
@@ -7926,7 +7944,7 @@ int ring_buffer_map_get_reader(struct trace_buffer *buffer, int cpu)
 out:
 	/* Some archs do not have data cache coherency between kernel and user-space */
 	flush_kernel_vmap_range(cpu_buffer->reader_page->page,
-				buffer->subbuf_size + BUF_PAGE_HDR_SIZE);
+				rb_subbuf_size(buffer));
 
 	rb_update_meta_page(cpu_buffer);
 
-- 
2.55.0.654.g21b8a5bc05-goog


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

* [PATCH 5/6] ring-buffer: Dynamically calculate max_data_size
  2026-08-06 21:13 [PATCH 0/6] ring-buffer: Fixes for subbuf resizing and persistent buffers Vincent Donnefort
                   ` (3 preceding siblings ...)
  2026-08-06 21:13 ` [PATCH 4/6] ring-buffer: Fix subbuf resize concurrency Vincent Donnefort
@ 2026-08-06 21:13 ` Vincent Donnefort
  2026-08-06 21:13 ` [PATCH 6/6] ring-buffer: Remove ring_buffer_per_cpu::mapped Vincent Donnefort
  5 siblings, 0 replies; 15+ messages in thread
From: Vincent Donnefort @ 2026-08-06 21:13 UTC (permalink / raw)
  To: rostedt, mhiramat, linux-trace-kernel
  Cc: mathieu.desnoyers, kernel-team, linux-kernel, Vincent Donnefort

The ring buffer order can be dynamically modified and temporarily
disables writing to do so. It is therefore safe to use the updated value
to calculate the maximum event size which can be written onto the ring
buffer.

However, notice it is hardly making any difference for trace_marker
because of the TRACE_MARKER_MAX_SIZE limit. For an 8KiB subbuf size,
trace_marker can take 4096 characters while it can 'only' take 4054
bytes for smaller subbufs.

Fixes: f9b94daa542a ("ring-buffer: Set new size of the ring buffer sub page")
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>

diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 3531005aab43..d2480ccc81b8 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -587,7 +587,6 @@ struct trace_buffer {
 	struct ring_buffer_meta		*meta;
 
 	unsigned int			subbuf_order;
-	unsigned int			max_data_size;
 };
 
 static inline unsigned int rb_subbuf_size(struct trace_buffer *buffer)
@@ -600,6 +599,17 @@ static inline unsigned int rb_subbuf_capacity(struct trace_buffer *buffer)
 	return rb_subbuf_size(buffer) - BUF_PAGE_HDR_SIZE;
 }
 
+static inline unsigned int rb_max_data_size(struct trace_buffer *buffer)
+{
+	struct ring_buffer_event *event;
+
+	/*
+	 * surely rb_subbuf_capacity() is bigger than
+	 * RINGBUF_TYPE_DATA_TYPE_LEN_MAX (see ring_buffer_event_length).
+	 */
+	return rb_subbuf_capacity(buffer) - RB_EVNT_HDR_SIZE - sizeof(event->array[0]);
+}
+
 static inline unsigned int rb_page_capacity(struct buffer_page *bpage)
 {
 	return (PAGE_SIZE << bpage->order) - BUF_PAGE_HDR_SIZE;
@@ -2745,9 +2755,6 @@ static struct trace_buffer *alloc_buffer(unsigned long size, unsigned flags,
 	buffer->subbuf_order = order;
 	subbuf_size = (PAGE_SIZE << order);
 
-	/* Max payload is buffer page size - header (8bytes) */
-	buffer->max_data_size = rb_subbuf_capacity(buffer) - (sizeof(u32) * 2);
-
 	buffer->flags = flags;
 	buffer->clock = trace_clock_local;
 	buffer->reader_lock_key = key;
@@ -4914,7 +4921,7 @@ rb_reserve_next_event(struct trace_buffer *buffer,
 	if (ring_buffer_time_stamp_abs(cpu_buffer->buffer)) {
 		add_ts_default = RB_ADD_STAMP_ABSOLUTE;
 		info.length += RB_LEN_TIME_EXTEND;
-		if (info.length > cpu_buffer->buffer->max_data_size)
+		if (info.length > rb_max_data_size(cpu_buffer->buffer))
 			goto out_fail;
 	} else {
 		add_ts_default = RB_ADD_STAMP_NONE;
@@ -4989,7 +4996,7 @@ ring_buffer_lock_reserve(struct trace_buffer *buffer, unsigned long length)
 	if (unlikely(atomic_read(&cpu_buffer->record_disabled)))
 		goto out;
 
-	if (unlikely(length > buffer->max_data_size))
+	if (unlikely(length > rb_max_data_size(buffer)))
 		goto out;
 
 	if (unlikely(trace_recursive_lock(cpu_buffer)))
@@ -5136,7 +5143,7 @@ int ring_buffer_write(struct trace_buffer *buffer,
 	if (atomic_read(&cpu_buffer->record_disabled))
 		return -EBUSY;
 
-	if (length > buffer->max_data_size)
+	if (length > rb_max_data_size(buffer))
 		return -EBUSY;
 
 	if (unlikely(trace_recursive_lock(cpu_buffer)))
@@ -6495,8 +6502,9 @@ unsigned long ring_buffer_max_event_size(struct trace_buffer *buffer)
 {
 	/* If abs timestamp is requested, events have a timestamp too */
 	if (ring_buffer_time_stamp_abs(buffer))
-		return buffer->max_data_size - RB_LEN_TIME_EXTEND;
-	return buffer->max_data_size;
+		return rb_max_data_size(buffer) - RB_LEN_TIME_EXTEND;
+
+	return rb_max_data_size(buffer);
 }
 EXPORT_SYMBOL_GPL(ring_buffer_max_event_size);
 
-- 
2.55.0.654.g21b8a5bc05-goog


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

* [PATCH 6/6] ring-buffer: Remove ring_buffer_per_cpu::mapped
  2026-08-06 21:13 [PATCH 0/6] ring-buffer: Fixes for subbuf resizing and persistent buffers Vincent Donnefort
                   ` (4 preceding siblings ...)
  2026-08-06 21:13 ` [PATCH 5/6] ring-buffer: Dynamically calculate max_data_size Vincent Donnefort
@ 2026-08-06 21:13 ` Vincent Donnefort
  5 siblings, 0 replies; 15+ messages in thread
From: Vincent Donnefort @ 2026-08-06 21:13 UTC (permalink / raw)
  To: rostedt, mhiramat, linux-trace-kernel
  Cc: mathieu.desnoyers, kernel-team, linux-kernel, Vincent Donnefort

ring_buffer_per_cpu::mapped tracks if a ring-buffer is either mapped by
user-space or if it is a persistent buffer. We already have user_mapped
for the former and ring_meta for the latter. Get rid of mapped and
instead create rb_is_static(). A static ring-buffer cannot be resized,
swapped or have its pages extracted.

Signed-off-by: Vincent Donnefort <vdonnefort@google.com>

diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index d2480ccc81b8..e18e2c315545 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -503,7 +503,7 @@ struct ring_buffer_per_cpu {
 	int				cpu;
 	atomic_t			record_disabled;
 	atomic_t			resize_disabled;
-	struct trace_buffer	*buffer;
+	struct trace_buffer		*buffer;
 	raw_spinlock_t			reader_lock;	/* serialize readers */
 	arch_spinlock_t			lock;
 	struct lock_class_key		lock_key;
@@ -541,7 +541,6 @@ struct ring_buffer_per_cpu {
 	/* pages removed since last reset */
 	unsigned long			pages_removed;
 
-	unsigned int			mapped;
 	unsigned int			user_mapped;	/* user space mapping */
 	struct mutex			mapping_lock;
 	struct buffer_page		**subbuf_ids;	/* ID to subbuf VA */
@@ -615,6 +614,11 @@ static inline unsigned int rb_page_capacity(struct buffer_page *bpage)
 	return (PAGE_SIZE << bpage->order) - BUF_PAGE_HDR_SIZE;
 }
 
+static inline bool rb_is_static(struct ring_buffer_per_cpu *cpu_buffer)
+{
+	return cpu_buffer->user_mapped || cpu_buffer->remote || cpu_buffer->ring_meta;
+}
+
 struct ring_buffer_iter {
 	struct ring_buffer_per_cpu	*cpu_buffer;
 	unsigned long			head;
@@ -2545,7 +2549,6 @@ rb_allocate_cpu_buffer(struct trace_buffer *buffer, long nr_pages, int cpu)
 		 * Range mapped buffers have the same restrictions as memory
 		 * mapped ones do.
 		 */
-		cpu_buffer->mapped = 1;
 		cpu_buffer->ring_meta = rb_range_meta(buffer, nr_pages, cpu);
 		bpage->page = rb_range_buffer(cpu_buffer, 0);
 		if (!bpage->page)
@@ -6636,12 +6639,11 @@ rb_reset_cpu(struct ring_buffer_per_cpu *cpu_buffer)
 	rb_head_page_activate(cpu_buffer);
 	cpu_buffer->pages_removed = 0;
 
-	if (cpu_buffer->mapped) {
-		rb_update_meta_page(cpu_buffer);
-		if (cpu_buffer->ring_meta) {
-			struct ring_buffer_cpu_meta *meta = cpu_buffer->ring_meta;
-			meta->commit_buffer = meta->head_buffer;
-		}
+	rb_update_meta_page(cpu_buffer);
+	if (cpu_buffer->ring_meta) {
+		struct ring_buffer_cpu_meta *meta = cpu_buffer->ring_meta;
+
+		meta->commit_buffer = meta->head_buffer;
 	}
 }
 
@@ -6890,8 +6892,8 @@ int ring_buffer_swap_cpu(struct trace_buffer *buffer_a,
 	cpu_buffer_a = buffer_a->buffers[cpu];
 	cpu_buffer_b = buffer_b->buffers[cpu];
 
-	/* It's up to the callers to not try to swap mapped buffers */
-	if (WARN_ON_ONCE(cpu_buffer_a->mapped || cpu_buffer_b->mapped))
+	/* It's up to the callers to not try to swap static buffers */
+	if (WARN_ON_ONCE(rb_is_static(cpu_buffer_a) || rb_is_static(cpu_buffer_b)))
 		return -EBUSY;
 
 	/* At least make sure the two buffers are somewhat the same */
@@ -7103,7 +7105,6 @@ int ring_buffer_read_page(struct trace_buffer *buffer,
 	unsigned int size;
 	unsigned int read;
 	u64 save_timestamp;
-	bool force_memcpy;
 
 	if (!cpumask_test_cpu(cpu, buffer->cpumask))
 		return -1;
@@ -7142,8 +7143,6 @@ int ring_buffer_read_page(struct trace_buffer *buffer,
 	/* Check if any events were dropped */
 	missed_events = cpu_buffer->lost_events;
 
-	force_memcpy = cpu_buffer->mapped || cpu_buffer->remote;
-
 	/*
 	 * If this page has been partially read or
 	 * if len is not big enough to read the rest of the page or
@@ -7153,7 +7152,7 @@ int ring_buffer_read_page(struct trace_buffer *buffer,
 	 */
 	if (read || (len < (size - read)) ||
 	    cpu_buffer->reader_page == cpu_buffer->commit_page ||
-	    force_memcpy) {
+	    rb_is_static(cpu_buffer)) {
 		struct buffer_data_page *rpage = cpu_buffer->reader_page->page;
 		unsigned int rpos = read;
 		unsigned int pos = 0;
@@ -7600,11 +7599,7 @@ static int __rb_inc_dec_mapped(struct ring_buffer_per_cpu *cpu_buffer,
 
 	lockdep_assert_held(&cpu_buffer->mapping_lock);
 
-	/* mapped is always greater or equal to user_mapped */
-	if (WARN_ON(cpu_buffer->mapped < cpu_buffer->user_mapped))
-		return -EINVAL;
-
-	if (inc && cpu_buffer->mapped == UINT_MAX)
+	if (inc && cpu_buffer->user_mapped == UINT_MAX)
 		return -EBUSY;
 
 	if (WARN_ON(!inc && cpu_buffer->user_mapped == 0))
@@ -7613,13 +7608,10 @@ static int __rb_inc_dec_mapped(struct ring_buffer_per_cpu *cpu_buffer,
 	mutex_lock(&cpu_buffer->buffer->mutex);
 	raw_spin_lock_irqsave(&cpu_buffer->reader_lock, flags);
 
-	if (inc) {
+	if (inc)
 		cpu_buffer->user_mapped++;
-		cpu_buffer->mapped++;
-	} else {
+	else
 		cpu_buffer->user_mapped--;
-		cpu_buffer->mapped--;
-	}
 
 	raw_spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags);
 	mutex_unlock(&cpu_buffer->buffer->mutex);
@@ -7791,7 +7783,6 @@ int ring_buffer_map(struct trace_buffer *buffer, int cpu,
 	if (!err) {
 		raw_spin_lock_irqsave(&cpu_buffer->reader_lock, flags);
 		/* This is the first time it is mapped by user */
-		cpu_buffer->mapped++;
 		cpu_buffer->user_mapped = 1;
 		raw_spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags);
 	} else {
@@ -7848,8 +7839,6 @@ int ring_buffer_unmap(struct trace_buffer *buffer, int cpu)
 	raw_spin_lock_irqsave(&cpu_buffer->reader_lock, flags);
 
 	/* This is the last user space mapping */
-	if (!WARN_ON_ONCE(cpu_buffer->mapped < cpu_buffer->user_mapped))
-		cpu_buffer->mapped--;
 	cpu_buffer->user_mapped = 0;
 
 	raw_spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags);
-- 
2.55.0.654.g21b8a5bc05-goog


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

* Re: [PATCH 1/6] ring-buffer: Prevent resizing of persistent ring buffer
  2026-08-06 21:13 ` [PATCH 1/6] ring-buffer: Prevent resizing of persistent ring buffer Vincent Donnefort
@ 2026-08-07  2:18   ` Masami Hiramatsu
  2026-08-07  8:14     ` Vincent Donnefort
  0 siblings, 1 reply; 15+ messages in thread
From: Masami Hiramatsu @ 2026-08-07  2:18 UTC (permalink / raw)
  To: Vincent Donnefort
  Cc: rostedt, linux-trace-kernel, mathieu.desnoyers, kernel-team,
	linux-kernel

On Thu,  6 Aug 2026 22:13:01 +0100
Vincent Donnefort <vdonnefort@google.com> wrote:

> Dynamically resizing a persistent ring buffer is not possible. Disable
> the feature.

Is it true? Of course there is meaningless to resize the persistent
ring buffer (because it makes the buffer none-persistent), we are currently
allows user to resize it (like for resizing unused persistent ring buffer)

Thank you,

> 
> Fixes: be68d63a139b ("ring-buffer: Add ring_buffer_alloc_range()")
> Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
> 
> diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
> index 8e2485bb3aa8..afe75ad2bbf2 100644
> --- a/kernel/trace/ring_buffer.c
> +++ b/kernel/trace/ring_buffer.c
> @@ -2528,6 +2528,8 @@ rb_allocate_cpu_buffer(struct trace_buffer *buffer, long nr_pages, int cpu)
>  		if (cpu_buffer->ring_meta->head_buffer)
>  			rb_meta_buffer_update(cpu_buffer, bpage);
>  		bpage->range = 1;
> +
> +		atomic_inc(&cpu_buffer->resize_disabled);
>  	} else if (buffer->remote) {
>  		struct ring_buffer_desc *desc = ring_buffer_desc(buffer->remote->desc, cpu);
>  
> -- 
> 2.55.0.654.g21b8a5bc05-goog
> 


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

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

* Re: [PATCH 1/6] ring-buffer: Prevent resizing of persistent ring buffer
  2026-08-07  2:18   ` Masami Hiramatsu
@ 2026-08-07  8:14     ` Vincent Donnefort
  2026-08-07  9:43       ` Vincent Donnefort
  0 siblings, 1 reply; 15+ messages in thread
From: Vincent Donnefort @ 2026-08-07  8:14 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: rostedt, linux-trace-kernel, mathieu.desnoyers, kernel-team,
	linux-kernel

On Fri, Aug 07, 2026 at 11:18:08AM +0900, Masami Hiramatsu wrote:
> On Thu,  6 Aug 2026 22:13:01 +0100
> Vincent Donnefort <vdonnefort@google.com> wrote:
> 
> > Dynamically resizing a persistent ring buffer is not possible. Disable
> > the feature.
> 
> Is it true? Of course there is meaningless to resize the persistent
> ring buffer (because it makes the buffer none-persistent), we are currently
> allows user to resize it (like for resizing unused persistent ring buffer)

__rb_allocate_pages() in ring_buffer_resize() would call for a persistent buffer
rb_range_buffer(), which IIUC, is just reusing the same ring buffer pages as the
one already in the persistent buffer.

So, reducing the size would surely work, however increasing it, would most
likely mean having buffer_page pointing to the same buffer_data_page?

Also, the comment

  /* 
   * Range mapped buffers have the same restrictions as memory
   * mapped ones do.
   */

Made me think that resize_disabled was omitted.

> 
> Thank you,
> 
> > 
> > Fixes: be68d63a139b ("ring-buffer: Add ring_buffer_alloc_range()")
> > Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
> > 
> > diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
> > index 8e2485bb3aa8..afe75ad2bbf2 100644
> > --- a/kernel/trace/ring_buffer.c
> > +++ b/kernel/trace/ring_buffer.c
> > @@ -2528,6 +2528,8 @@ rb_allocate_cpu_buffer(struct trace_buffer *buffer, long nr_pages, int cpu)
> >  		if (cpu_buffer->ring_meta->head_buffer)
> >  			rb_meta_buffer_update(cpu_buffer, bpage);
> >  		bpage->range = 1;
> > +
> > +		atomic_inc(&cpu_buffer->resize_disabled);
> >  	} else if (buffer->remote) {
> >  		struct ring_buffer_desc *desc = ring_buffer_desc(buffer->remote->desc, cpu);
> >  
> > -- 
> > 2.55.0.654.g21b8a5bc05-goog
> > 
> 
> 
> -- 
> Masami Hiramatsu (Google) <mhiramat@kernel.org>

-- 
Vincent

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

* Re: [PATCH 1/6] ring-buffer: Prevent resizing of persistent ring buffer
  2026-08-07  8:14     ` Vincent Donnefort
@ 2026-08-07  9:43       ` Vincent Donnefort
  2026-08-07 10:25         ` Vincent Donnefort
  2026-08-07 14:45         ` Steven Rostedt
  0 siblings, 2 replies; 15+ messages in thread
From: Vincent Donnefort @ 2026-08-07  9:43 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: rostedt, linux-trace-kernel, mathieu.desnoyers, kernel-team,
	linux-kernel

On Fri, Aug 07, 2026 at 09:14:26AM +0100, Vincent Donnefort wrote:
> On Fri, Aug 07, 2026 at 11:18:08AM +0900, Masami Hiramatsu wrote:
> > On Thu,  6 Aug 2026 22:13:01 +0100
> > Vincent Donnefort <vdonnefort@google.com> wrote:
> > 
> > > Dynamically resizing a persistent ring buffer is not possible. Disable
> > > the feature.
> > 
> > Is it true? Of course there is meaningless to resize the persistent
> > ring buffer (because it makes the buffer none-persistent), we are currently
> > allows user to resize it (like for resizing unused persistent ring buffer)
> 
> __rb_allocate_pages() in ring_buffer_resize() would call for a persistent buffer
> rb_range_buffer(), which IIUC, is just reusing the same ring buffer pages as the
> one already in the persistent buffer.

I have just tried and if reducing the size works, increasing fails in both
rb_set_head_page() and rb_insert_pages() with a warning, which I believe is
expected.

We could improve that, but it feels like it is a lot of work for a meaningless
feature which we should just disable?

-- 
Vincent

> 
> So, reducing the size would surely work, however increasing it, would most
> likely mean having buffer_page pointing to the same buffer_data_page?
> 
> Also, the comment
> 
>   /* 
>    * Range mapped buffers have the same restrictions as memory
>    * mapped ones do.
>    */
> 
> Made me think that resize_disabled was omitted.
> 
> > 
> > Thank you,
> > 
> > > 
> > > Fixes: be68d63a139b ("ring-buffer: Add ring_buffer_alloc_range()")
> > > Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
> > > 
> > > diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
> > > index 8e2485bb3aa8..afe75ad2bbf2 100644
> > > --- a/kernel/trace/ring_buffer.c
> > > +++ b/kernel/trace/ring_buffer.c
> > > @@ -2528,6 +2528,8 @@ rb_allocate_cpu_buffer(struct trace_buffer *buffer, long nr_pages, int cpu)
> > >  		if (cpu_buffer->ring_meta->head_buffer)
> > >  			rb_meta_buffer_update(cpu_buffer, bpage);
> > >  		bpage->range = 1;
> > > +
> > > +		atomic_inc(&cpu_buffer->resize_disabled);
> > >  	} else if (buffer->remote) {
> > >  		struct ring_buffer_desc *desc = ring_buffer_desc(buffer->remote->desc, cpu);
> > >  
> > > -- 
> > > 2.55.0.654.g21b8a5bc05-goog
> > > 
> > 
> > 
> > -- 
> > Masami Hiramatsu (Google) <mhiramat@kernel.org>
> 
> -- 
> Vincent


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

* Re: [PATCH 1/6] ring-buffer: Prevent resizing of persistent ring buffer
  2026-08-07  9:43       ` Vincent Donnefort
@ 2026-08-07 10:25         ` Vincent Donnefort
  2026-08-07 14:45         ` Steven Rostedt
  1 sibling, 0 replies; 15+ messages in thread
From: Vincent Donnefort @ 2026-08-07 10:25 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: rostedt, linux-trace-kernel, mathieu.desnoyers, kernel-team,
	linux-kernel

On Fri, Aug 07, 2026 at 10:43:12AM +0100, Vincent Donnefort wrote:
> On Fri, Aug 07, 2026 at 09:14:26AM +0100, Vincent Donnefort wrote:
> > On Fri, Aug 07, 2026 at 11:18:08AM +0900, Masami Hiramatsu wrote:
> > > On Thu,  6 Aug 2026 22:13:01 +0100
> > > Vincent Donnefort <vdonnefort@google.com> wrote:
> > > 
> > > > Dynamically resizing a persistent ring buffer is not possible. Disable
> > > > the feature.
> > > 
> > > Is it true? Of course there is meaningless to resize the persistent
> > > ring buffer (because it makes the buffer none-persistent), we are currently
> > > allows user to resize it (like for resizing unused persistent ring buffer)
> > 
> > __rb_allocate_pages() in ring_buffer_resize() would call for a persistent buffer
> > rb_range_buffer(), which IIUC, is just reusing the same ring buffer pages as the
> > one already in the persistent buffer.

With more logs, during a resize form 8 to 16K: 

cpu_buffer->new_pages contains:

[  632.919017] ring_buffer_resize: CPU 0 NEW page 00000000768ccc81
[  632.919828] ring_buffer_resize: CPU 0 NEW page 00000000ee48729c

while cpu_buffer->pages contains:

[  632.921511] ring_buffer_resize: CPU 0 OLD page 000000002c4c6f92
[  632.921917] ring_buffer_resize: CPU 0 OLD page 00000000dadcb510
[  632.922295] ring_buffer_resize: CPU 0 OLD page 00000000768ccc81
[  632.923226] ring_buffer_resize: CPU 0 OLD reader page 000000003b4dd5ba

So two buffer_page point to 00000000768ccc81.

-- 
Vincent

> 
> I have just tried and if reducing the size works, increasing fails in both
> rb_set_head_page() and rb_insert_pages() with a warning, which I believe is
> expected.
> 
> We could improve that, but it feels like it is a lot of work for a meaningless
> feature which we should just disable?
> 
> -- 
> Vincent
> 
> > 
> > So, reducing the size would surely work, however increasing it, would most
> > likely mean having buffer_page pointing to the same buffer_data_page?
> > 
> > Also, the comment
> > 
> >   /* 
> >    * Range mapped buffers have the same restrictions as memory
> >    * mapped ones do.
> >    */
> > 
> > Made me think that resize_disabled was omitted.
> > 
> > > 
> > > Thank you,
> > > 
> > > > 
> > > > Fixes: be68d63a139b ("ring-buffer: Add ring_buffer_alloc_range()")
> > > > Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
> > > > 
> > > > diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
> > > > index 8e2485bb3aa8..afe75ad2bbf2 100644
> > > > --- a/kernel/trace/ring_buffer.c
> > > > +++ b/kernel/trace/ring_buffer.c
> > > > @@ -2528,6 +2528,8 @@ rb_allocate_cpu_buffer(struct trace_buffer *buffer, long nr_pages, int cpu)
> > > >  		if (cpu_buffer->ring_meta->head_buffer)
> > > >  			rb_meta_buffer_update(cpu_buffer, bpage);
> > > >  		bpage->range = 1;
> > > > +
> > > > +		atomic_inc(&cpu_buffer->resize_disabled);
> > > >  	} else if (buffer->remote) {
> > > >  		struct ring_buffer_desc *desc = ring_buffer_desc(buffer->remote->desc, cpu);
> > > >  
> > > > -- 
> > > > 2.55.0.654.g21b8a5bc05-goog
> > > > 
> > > 
> > > 
> > > -- 
> > > Masami Hiramatsu (Google) <mhiramat@kernel.org>
> > 
> > -- 
> > Vincent
> 

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

* Re: [PATCH 1/6] ring-buffer: Prevent resizing of persistent ring buffer
  2026-08-07  9:43       ` Vincent Donnefort
  2026-08-07 10:25         ` Vincent Donnefort
@ 2026-08-07 14:45         ` Steven Rostedt
  2026-08-07 15:25           ` Vincent Donnefort
  1 sibling, 1 reply; 15+ messages in thread
From: Steven Rostedt @ 2026-08-07 14:45 UTC (permalink / raw)
  To: Vincent Donnefort
  Cc: Masami Hiramatsu, linux-trace-kernel, mathieu.desnoyers,
	kernel-team, linux-kernel

On Fri, 7 Aug 2026 10:43:12 +0100
Vincent Donnefort <vdonnefort@google.com> wrote:

> On Fri, Aug 07, 2026 at 09:14:26AM +0100, Vincent Donnefort wrote:
> > On Fri, Aug 07, 2026 at 11:18:08AM +0900, Masami Hiramatsu wrote:  
> > > On Thu,  6 Aug 2026 22:13:01 +0100
> > > Vincent Donnefort <vdonnefort@google.com> wrote:
> > >   
> > > > Dynamically resizing a persistent ring buffer is not possible. Disable
> > > > the feature.  
> > > 
> > > Is it true? Of course there is meaningless to resize the persistent
> > > ring buffer (because it makes the buffer none-persistent), we are currently
> > > allows user to resize it (like for resizing unused persistent ring buffer)  
> > 
> > __rb_allocate_pages() in ring_buffer_resize() would call for a persistent buffer
> > rb_range_buffer(), which IIUC, is just reusing the same ring buffer pages as the
> > one already in the persistent buffer.  
> 
> I have just tried and if reducing the size works, increasing fails in both
> rb_set_head_page() and rb_insert_pages() with a warning, which I believe is
> expected.
> 
> We could improve that, but it feels like it is a lot of work for a meaningless
> feature which we should just disable?

Resizing a persistent ring buffer to a smaller size may be allowed, but I
see no point in increasing the size. Making it smaller should allow us to
give back a portion of the persistent ring buffer for general usage.

-- Steve

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

* Re: [PATCH 1/6] ring-buffer: Prevent resizing of persistent ring buffer
  2026-08-07 14:45         ` Steven Rostedt
@ 2026-08-07 15:25           ` Vincent Donnefort
  2026-08-07 15:45             ` Vincent Donnefort
  0 siblings, 1 reply; 15+ messages in thread
From: Vincent Donnefort @ 2026-08-07 15:25 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Masami Hiramatsu, linux-trace-kernel, mathieu.desnoyers,
	kernel-team, linux-kernel

On Fri, Aug 07, 2026 at 10:45:26AM -0400, Steven Rostedt wrote:
> On Fri, 7 Aug 2026 10:43:12 +0100
> Vincent Donnefort <vdonnefort@google.com> wrote:
> 
> > On Fri, Aug 07, 2026 at 09:14:26AM +0100, Vincent Donnefort wrote:
> > > On Fri, Aug 07, 2026 at 11:18:08AM +0900, Masami Hiramatsu wrote:  
> > > > On Thu,  6 Aug 2026 22:13:01 +0100
> > > > Vincent Donnefort <vdonnefort@google.com> wrote:
> > > >   
> > > > > Dynamically resizing a persistent ring buffer is not possible. Disable
> > > > > the feature.  
> > > > 
> > > > Is it true? Of course there is meaningless to resize the persistent
> > > > ring buffer (because it makes the buffer none-persistent), we are currently
> > > > allows user to resize it (like for resizing unused persistent ring buffer)  
> > > 
> > > __rb_allocate_pages() in ring_buffer_resize() would call for a persistent buffer
> > > rb_range_buffer(), which IIUC, is just reusing the same ring buffer pages as the
> > > one already in the persistent buffer.  
> > 
> > I have just tried and if reducing the size works, increasing fails in both
> > rb_set_head_page() and rb_insert_pages() with a warning, which I believe is
> > expected.
> > 
> > We could improve that, but it feels like it is a lot of work for a meaningless
> > feature which we should just disable?
> 
> Resizing a persistent ring buffer to a smaller size may be allowed, but I
> see no point in increasing the size. Making it smaller should allow us to
> give back a portion of the persistent ring buffer for general usage.
> 
> -- Steve

While I see the appeal to reclaim that memory, I don't think we have any good
interface for that. There is no nice way to get the list of pages that have been
freed and we have no control over what part of the ring-buffer is removed.

Also, as this memory is from a reserved-range, is there really a way to re-inject
it into the buddy allocator?

Perhaps what would make sense for resizing would be to support a CMA pool as a
persistent buffer?

-- 
Vincent

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

* Re: [PATCH 1/6] ring-buffer: Prevent resizing of persistent ring buffer
  2026-08-07 15:25           ` Vincent Donnefort
@ 2026-08-07 15:45             ` Vincent Donnefort
  2026-08-07 19:26               ` Steven Rostedt
  0 siblings, 1 reply; 15+ messages in thread
From: Vincent Donnefort @ 2026-08-07 15:45 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Masami Hiramatsu, linux-trace-kernel, mathieu.desnoyers,
	kernel-team, linux-kernel

On Fri, Aug 07, 2026 at 04:25:33PM +0100, Vincent Donnefort wrote:
> On Fri, Aug 07, 2026 at 10:45:26AM -0400, Steven Rostedt wrote:
> > On Fri, 7 Aug 2026 10:43:12 +0100
> > Vincent Donnefort <vdonnefort@google.com> wrote:
> > 
> > > On Fri, Aug 07, 2026 at 09:14:26AM +0100, Vincent Donnefort wrote:
> > > > On Fri, Aug 07, 2026 at 11:18:08AM +0900, Masami Hiramatsu wrote:  
> > > > > On Thu,  6 Aug 2026 22:13:01 +0100
> > > > > Vincent Donnefort <vdonnefort@google.com> wrote:
> > > > >   
> > > > > > Dynamically resizing a persistent ring buffer is not possible. Disable
> > > > > > the feature.  
> > > > > 
> > > > > Is it true? Of course there is meaningless to resize the persistent
> > > > > ring buffer (because it makes the buffer none-persistent), we are currently
> > > > > allows user to resize it (like for resizing unused persistent ring buffer)  
> > > > 
> > > > __rb_allocate_pages() in ring_buffer_resize() would call for a persistent buffer
> > > > rb_range_buffer(), which IIUC, is just reusing the same ring buffer pages as the
> > > > one already in the persistent buffer.  
> > > 
> > > I have just tried and if reducing the size works, increasing fails in both
> > > rb_set_head_page() and rb_insert_pages() with a warning, which I believe is
> > > expected.
> > > 
> > > We could improve that, but it feels like it is a lot of work for a meaningless
> > > feature which we should just disable?
> > 
> > Resizing a persistent ring buffer to a smaller size may be allowed, but I
> > see no point in increasing the size. Making it smaller should allow us to
> > give back a portion of the persistent ring buffer for general usage.
> > 
> > -- Steve
> 
> While I see the appeal to reclaim that memory, I don't think we have any good
> interface for that. There is no nice way to get the list of pages that have been
> freed and we have no control over what part of the ring-buffer is removed.
> 
> Also, as this memory is from a reserved-range, is there really a way to re-inject
> it into the buddy allocator?

free_reserved_page() would do actually. But then it is definitive. 

Happy to implement something like that. That also means that the instance can be
actually freed?

> 
> Perhaps what would make sense for resizing would be to support a CMA pool as a
> persistent buffer?
> 
> -- 
> Vincent

-- 
Vincent

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

* Re: [PATCH 1/6] ring-buffer: Prevent resizing of persistent ring buffer
  2026-08-07 15:45             ` Vincent Donnefort
@ 2026-08-07 19:26               ` Steven Rostedt
  0 siblings, 0 replies; 15+ messages in thread
From: Steven Rostedt @ 2026-08-07 19:26 UTC (permalink / raw)
  To: Vincent Donnefort
  Cc: Masami Hiramatsu, linux-trace-kernel, mathieu.desnoyers,
	kernel-team, linux-kernel

On Fri, 7 Aug 2026 16:45:23 +0100
Vincent Donnefort <vdonnefort@google.com> wrote:

> free_reserved_page() would do actually. But then it is definitive. 

It's not always a reserved page.

> 
> Happy to implement something like that. That also means that the instance can be
> actually freed?

They can be freed now. Try a rmdir on one.

Note implementing this is not straight forward. What I would suggest is
that because the persistent ring buffers are contiguous, to resize, you
basically need to remap to the new size. That means each of the buffers
will still be attached to each other.

What would need to be done is:

  1. calculate the new size needed to accommodate all the CPU buffers.
  2. Split them up within the new size region.
  3. Then free the remaining pages.

Obviously, access to the buffer from readers and writers will need to be
prohibited while this is happening.

-- Steve


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

end of thread, other threads:[~2026-08-07 19:26 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-06 21:13 [PATCH 0/6] ring-buffer: Fixes for subbuf resizing and persistent buffers Vincent Donnefort
2026-08-06 21:13 ` [PATCH 1/6] ring-buffer: Prevent resizing of persistent ring buffer Vincent Donnefort
2026-08-07  2:18   ` Masami Hiramatsu
2026-08-07  8:14     ` Vincent Donnefort
2026-08-07  9:43       ` Vincent Donnefort
2026-08-07 10:25         ` Vincent Donnefort
2026-08-07 14:45         ` Steven Rostedt
2026-08-07 15:25           ` Vincent Donnefort
2026-08-07 15:45             ` Vincent Donnefort
2026-08-07 19:26               ` Steven Rostedt
2026-08-06 21:13 ` [PATCH 2/6] ring-buffer: Prevent subbuf order change when resizing is disabled Vincent Donnefort
2026-08-06 21:13 ` [PATCH 3/6] ring-buffer: Initialise reader page order in rb_allocate_cpu_buffer() Vincent Donnefort
2026-08-06 21:13 ` [PATCH 4/6] ring-buffer: Fix subbuf resize concurrency Vincent Donnefort
2026-08-06 21:13 ` [PATCH 5/6] ring-buffer: Dynamically calculate max_data_size Vincent Donnefort
2026-08-06 21:13 ` [PATCH 6/6] ring-buffer: Remove ring_buffer_per_cpu::mapped Vincent Donnefort

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