* [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).