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 <[email protected]>
---
 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


Reply via email to