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


Reply via email to