linux-trace-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] ring-buffer: Use kvmalloc variants for big allocations
@ 2026-09-22  7:29 Vincent Donnefort
  2026-09-22  7:29 ` [PATCH 1/4] ring-buffer: Use kvzalloc_objs for user mapping arrays Vincent Donnefort
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Vincent Donnefort @ 2026-09-22  7:29 UTC (permalink / raw)
  To: rostedt, mhiramat, linux-trace-kernel
  Cc: mathieu.desnoyers, kernel-team, linux-kernel, Vincent Donnefort

Several allocations in the ring buffer code scale with buffer capacity or
sub-buffer order and require high-order contiguous physical memory when
using plain kmalloc. Under memory fragmentation or with large buffers,
these allocations can fail unnecessarily.

This series converts those allocations to their kvmalloc equivalents.

Vincent Donnefort (4):
  ring-buffer: Use kvzalloc_objs for user mapping arrays
  ring-buffer: Use kvzalloc_objs for remote buffer subbuf_ids
  ring-buffer: Drop redundant ring_buffer_iter::event_size
  ring-buffer: Use kvmalloc for ring_buffer_iter::event

 kernel/trace/ring_buffer.c | 35 +++++++++++++++++++----------------
 1 file changed, 19 insertions(+), 16 deletions(-)


base-commit: 93f51579e7df248780214094418f205253383cc5
-- 
2.55.0.1082.g2b9226bbc0-goog


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

* [PATCH 1/4] ring-buffer: Use kvzalloc_objs for user mapping arrays
  2026-09-22  7:29 [PATCH 0/4] ring-buffer: Use kvmalloc variants for big allocations Vincent Donnefort
@ 2026-09-22  7:29 ` Vincent Donnefort
  2026-09-22  7:29 ` [PATCH 2/4] ring-buffer: Use kvzalloc_objs for remote buffer subbuf_ids Vincent Donnefort
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Vincent Donnefort @ 2026-09-22  7:29 UTC (permalink / raw)
  To: rostedt, mhiramat, linux-trace-kernel
  Cc: mathieu.desnoyers, kernel-team, linux-kernel, Vincent Donnefort

Mapping a large trace buffer to user space requires allocating an array
of struct bpage and one of struct page. For large ring buffers, these
contiguous allocations are likely to fail with memory fragmentation.

Switch both to kvzalloc_objs() to use the vmalloc fallback under memory
pressure.

Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
---
 kernel/trace/ring_buffer.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 04bb94c29f58..f9be87c2cc3d 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -7746,9 +7746,9 @@ static int __rb_map_vma(struct ring_buffer_per_cpu *cpu_buffer,
 			struct vm_area_struct *vma)
 {
 	unsigned long nr_subbufs, nr_pages, nr_vma_pages;
-	pgoff_t pgoff = vma_start_pgoff(vma);
+	struct page **pages __free(kvfree) = NULL;
 	unsigned int subbuf_pages, subbuf_order;
-	struct page **pages __free(kfree) = NULL;
+	pgoff_t pgoff = vma_start_pgoff(vma);
 	int p = 0, s = 0;
 	int err;
 
@@ -7785,7 +7785,7 @@ static int __rb_map_vma(struct ring_buffer_per_cpu *cpu_buffer,
 
 	nr_pages = nr_vma_pages;
 
-	pages = kzalloc_objs(*pages, nr_pages);
+	pages = kvzalloc_objs(*pages, nr_pages);
 	if (!pages)
 		return -ENOMEM;
 
@@ -7877,7 +7877,7 @@ int ring_buffer_map(struct trace_buffer *buffer, int cpu,
 		return err;
 
 	/* subbuf_ids includes the reader while nr_pages does not */
-	subbuf_ids = kcalloc(cpu_buffer->nr_pages + 1, sizeof(*subbuf_ids), GFP_KERNEL);
+	subbuf_ids = kvzalloc_objs(*subbuf_ids, cpu_buffer->nr_pages + 1);
 	if (!subbuf_ids) {
 		rb_free_meta_page(cpu_buffer);
 		return -ENOMEM;
@@ -7901,7 +7901,7 @@ int ring_buffer_map(struct trace_buffer *buffer, int cpu,
 		cpu_buffer->user_mapped = 1;
 		raw_spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags);
 	} else {
-		kfree(cpu_buffer->subbuf_ids);
+		kvfree(cpu_buffer->subbuf_ids);
 		cpu_buffer->subbuf_ids = NULL;
 		rb_free_meta_page(cpu_buffer);
 		atomic_dec(&cpu_buffer->resize_disabled);
@@ -7958,7 +7958,7 @@ int ring_buffer_unmap(struct trace_buffer *buffer, int cpu)
 
 	raw_spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags);
 
-	kfree(cpu_buffer->subbuf_ids);
+	kvfree(cpu_buffer->subbuf_ids);
 	cpu_buffer->subbuf_ids = NULL;
 	rb_free_meta_page(cpu_buffer);
 	atomic_dec(&cpu_buffer->resize_disabled);
-- 
2.55.0.1082.g2b9226bbc0-goog


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

* [PATCH 2/4] ring-buffer: Use kvzalloc_objs for remote buffer subbuf_ids
  2026-09-22  7:29 [PATCH 0/4] ring-buffer: Use kvmalloc variants for big allocations Vincent Donnefort
  2026-09-22  7:29 ` [PATCH 1/4] ring-buffer: Use kvzalloc_objs for user mapping arrays Vincent Donnefort
@ 2026-09-22  7:29 ` Vincent Donnefort
  2026-09-22  7:29 ` [PATCH 3/4] ring-buffer: Drop redundant ring_buffer_iter::event_size Vincent Donnefort
  2026-09-22  7:29 ` [PATCH 4/4] ring-buffer: Use kvmalloc for ring_buffer_iter::event Vincent Donnefort
  3 siblings, 0 replies; 5+ messages in thread
From: Vincent Donnefort @ 2026-09-22  7:29 UTC (permalink / raw)
  To: rostedt, mhiramat, linux-trace-kernel
  Cc: mathieu.desnoyers, kernel-team, linux-kernel, Vincent Donnefort

Creating a remote ring buffer requires allocating an array of bpage. For
large ring buffers, this contiguous allocation is likely to fail with
memory fragmentation.

Switch it to kvzalloc_objs() to use the vmalloc fallback under memory
pressure.

Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
---
 kernel/trace/ring_buffer.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index f9be87c2cc3d..1a158a24b3c8 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -2620,8 +2620,8 @@ rb_allocate_cpu_buffer(struct trace_buffer *buffer, unsigned long nr_pages, int
 		cpu_buffer->remote = buffer->remote;
 		cpu_buffer->meta_page = (struct trace_buffer_meta *)(void *)desc->meta_va;
 		cpu_buffer->nr_pages = nr_pages;
-		cpu_buffer->subbuf_ids = kzalloc_objs(*cpu_buffer->subbuf_ids,
-						      cpu_buffer->nr_pages + 1);
+		cpu_buffer->subbuf_ids = kvzalloc_objs(*cpu_buffer->subbuf_ids,
+						       cpu_buffer->nr_pages + 1);
 		if (!cpu_buffer->subbuf_ids)
 			goto fail_free_reader;
 
@@ -2681,7 +2681,7 @@ rb_allocate_cpu_buffer(struct trace_buffer *buffer, unsigned long nr_pages, int
 	return_ptr(cpu_buffer);
 
  fail_free_reader:
-	kfree(cpu_buffer->subbuf_ids);
+	kvfree(cpu_buffer->subbuf_ids);
 	free_buffer_page(cpu_buffer->reader_page);
 
 	return NULL;
@@ -2694,8 +2694,8 @@ static void rb_free_cpu_buffer(struct ring_buffer_per_cpu *cpu_buffer)
 
 	irq_work_sync(&cpu_buffer->irq_work.work);
 
-	if (cpu_buffer->remote)
-		kfree(cpu_buffer->subbuf_ids);
+	kvfree(cpu_buffer->subbuf_ids);
+	cpu_buffer->subbuf_ids = NULL;
 
 	free_buffer_page(cpu_buffer->reader_page);
 
-- 
2.55.0.1082.g2b9226bbc0-goog


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

* [PATCH 3/4] ring-buffer: Drop redundant ring_buffer_iter::event_size
  2026-09-22  7:29 [PATCH 0/4] ring-buffer: Use kvmalloc variants for big allocations Vincent Donnefort
  2026-09-22  7:29 ` [PATCH 1/4] ring-buffer: Use kvzalloc_objs for user mapping arrays Vincent Donnefort
  2026-09-22  7:29 ` [PATCH 2/4] ring-buffer: Use kvzalloc_objs for remote buffer subbuf_ids Vincent Donnefort
@ 2026-09-22  7:29 ` Vincent Donnefort
  2026-09-22  7:29 ` [PATCH 4/4] ring-buffer: Use kvmalloc for ring_buffer_iter::event Vincent Donnefort
  3 siblings, 0 replies; 5+ messages in thread
From: Vincent Donnefort @ 2026-09-22  7:29 UTC (permalink / raw)
  To: rostedt, mhiramat, linux-trace-kernel
  Cc: mathieu.desnoyers, kernel-team, linux-kernel, Vincent Donnefort

event_size contains the maximum size the iterator can read for each
event. It corresponds to the maximum capacity of a ring-buffer page.
During non-consuming read, resizing is disabled. It is therefore safe to
just use rb_subbuf_capacity(), making event_size redundant. Remove it.

Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
---
 kernel/trace/ring_buffer.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 1a158a24b3c8..3129589e2d0e 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -680,7 +680,6 @@ struct ring_buffer_iter {
 	u64				read_stamp;
 	u64				page_stamp;
 	struct ring_buffer_event	*event;
-	size_t				event_size;
 	int				missed_events;
 };
 
@@ -3558,9 +3557,11 @@ rb_iter_head_event(struct ring_buffer_iter *iter)
 	 */
 	barrier();
 
-	if ((iter->head + length) > commit || length > iter->event_size)
+	if ((iter->head + length) > commit ||
+	    length > rb_subbuf_capacity(iter->cpu_buffer->buffer)) {
 		/* Writer corrupted the read? */
 		goto reset;
+	}
 
 	memcpy(iter->event, event, length);
 	/*
@@ -6488,8 +6489,7 @@ ring_buffer_read_start(struct trace_buffer *buffer, int cpu, gfp_t 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);
+	iter->event = kmalloc(rb_subbuf_capacity(buffer), flags);
 	if (!iter->event) {
 		atomic_dec(&cpu_buffer->resize_disabled);
 		return NULL;
-- 
2.55.0.1082.g2b9226bbc0-goog


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

* [PATCH 4/4] ring-buffer: Use kvmalloc for ring_buffer_iter::event
  2026-09-22  7:29 [PATCH 0/4] ring-buffer: Use kvmalloc variants for big allocations Vincent Donnefort
                   ` (2 preceding siblings ...)
  2026-09-22  7:29 ` [PATCH 3/4] ring-buffer: Drop redundant ring_buffer_iter::event_size Vincent Donnefort
@ 2026-09-22  7:29 ` Vincent Donnefort
  3 siblings, 0 replies; 5+ messages in thread
From: Vincent Donnefort @ 2026-09-22  7:29 UTC (permalink / raw)
  To: rostedt, mhiramat, linux-trace-kernel
  Cc: mathieu.desnoyers, kernel-team, linux-kernel, Vincent Donnefort

The maximum size for an event correspond to the capacity of a single
ring buffer subbuf, which could be multiple pages, making this
contiguous allocation likely to fail with memory fragmentation

Switch it to kvmalloc() to use the vmalloc fallback under memory
pressure.

Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
---
 kernel/trace/ring_buffer.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 3129589e2d0e..f03fb9ed3372 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -6467,6 +6467,7 @@ 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;
+	unsigned int max_event_size;
 
 	if (!iter)
 		return NULL;
@@ -6489,7 +6490,9 @@ ring_buffer_read_start(struct trace_buffer *buffer, int cpu, gfp_t flags)
 		mutex_unlock(&buffer->mutex);
 
 	/* Holds the entire event: data and meta data. */
-	iter->event = kmalloc(rb_subbuf_capacity(buffer), flags);
+	max_event_size = rb_subbuf_capacity(buffer);
+	iter->event = gfpflags_allow_blocking(flags) ?
+		kvmalloc(max_event_size, flags) : kmalloc(max_event_size, flags);
 	if (!iter->event) {
 		atomic_dec(&cpu_buffer->resize_disabled);
 		return NULL;
@@ -6520,7 +6523,7 @@ ring_buffer_read_finish(struct ring_buffer_iter *iter)
 	rb_check_pages(cpu_buffer);
 
 	atomic_dec(&cpu_buffer->resize_disabled);
-	kfree(iter->event);
+	kvfree(iter->event);
 	kfree(iter);
 }
 EXPORT_SYMBOL_GPL(ring_buffer_read_finish);
-- 
2.55.0.1082.g2b9226bbc0-goog


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

end of thread, other threads:[~2026-09-22  7:29 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-22  7:29 [PATCH 0/4] ring-buffer: Use kvmalloc variants for big allocations Vincent Donnefort
2026-09-22  7:29 ` [PATCH 1/4] ring-buffer: Use kvzalloc_objs for user mapping arrays Vincent Donnefort
2026-09-22  7:29 ` [PATCH 2/4] ring-buffer: Use kvzalloc_objs for remote buffer subbuf_ids Vincent Donnefort
2026-09-22  7:29 ` [PATCH 3/4] ring-buffer: Drop redundant ring_buffer_iter::event_size Vincent Donnefort
2026-09-22  7:29 ` [PATCH 4/4] ring-buffer: Use kvmalloc for ring_buffer_iter::event Vincent Donnefort

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).