Do no trigger kernel console warnings when we try to allocate too many
pages, or a too large kmalloc area for page array (within a subbuffer),
or a sub-buffer array (within a buffer).
Use vmalloc/vfree for the "pages" local variable used only during
allocation, which is an array of nr_subbuf * nr_pages_per_subbuf
pointers. This ensures we do not limit the overall buffer size due to
kmalloc limitations.
Fixes #1031
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
#include <linux/slab.h>
#include <linux/cpu.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/cpu.h>
#include <linux/mm.h>
+#include <linux/vmalloc.h>
#include <wrapper/vmalloc.h> /* for wrapper_vmalloc_sync_all() */
#include <wrapper/ringbuffer/config.h>
#include <wrapper/vmalloc.h> /* for wrapper_vmalloc_sync_all() */
#include <wrapper/ringbuffer/config.h>
- pages = kmalloc_node(ALIGN(sizeof(*pages) * num_pages,
+ pages = vmalloc_node(ALIGN(sizeof(*pages) * num_pages,
1 << INTERNODE_CACHE_SHIFT),
1 << INTERNODE_CACHE_SHIFT),
- GFP_KERNEL, cpu_to_node(max(bufb->cpu, 0)));
+ cpu_to_node(max(bufb->cpu, 0)));
if (unlikely(!pages))
goto pages_error;
bufb->array = kmalloc_node(ALIGN(sizeof(*bufb->array)
* num_subbuf_alloc,
1 << INTERNODE_CACHE_SHIFT),
if (unlikely(!pages))
goto pages_error;
bufb->array = kmalloc_node(ALIGN(sizeof(*bufb->array)
* num_subbuf_alloc,
1 << INTERNODE_CACHE_SHIFT),
- GFP_KERNEL, cpu_to_node(max(bufb->cpu, 0)));
+ GFP_KERNEL | __GFP_NOWARN,
+ cpu_to_node(max(bufb->cpu, 0)));
if (unlikely(!bufb->array))
goto array_error;
for (i = 0; i < num_pages; i++) {
pages[i] = alloc_pages_node(cpu_to_node(max(bufb->cpu, 0)),
if (unlikely(!bufb->array))
goto array_error;
for (i = 0; i < num_pages; i++) {
pages[i] = alloc_pages_node(cpu_to_node(max(bufb->cpu, 0)),
- GFP_KERNEL | __GFP_ZERO, 0);
+ GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO, 0);
if (unlikely(!pages[i]))
goto depopulate;
}
if (unlikely(!pages[i]))
goto depopulate;
}
sizeof(struct lib_ring_buffer_backend_page)
* num_pages_per_subbuf,
1 << INTERNODE_CACHE_SHIFT),
sizeof(struct lib_ring_buffer_backend_page)
* num_pages_per_subbuf,
1 << INTERNODE_CACHE_SHIFT),
- GFP_KERNEL, cpu_to_node(max(bufb->cpu, 0)));
+ GFP_KERNEL | __GFP_NOWARN,
+ cpu_to_node(max(bufb->cpu, 0)));
if (!bufb->array[i])
goto free_array;
}
if (!bufb->array[i])
goto free_array;
}
sizeof(struct lib_ring_buffer_backend_subbuffer)
* num_subbuf,
1 << INTERNODE_CACHE_SHIFT),
sizeof(struct lib_ring_buffer_backend_subbuffer)
* num_subbuf,
1 << INTERNODE_CACHE_SHIFT),
- GFP_KERNEL, cpu_to_node(max(bufb->cpu, 0)));
+ GFP_KERNEL | __GFP_NOWARN,
+ cpu_to_node(max(bufb->cpu, 0)));
if (unlikely(!bufb->buf_wsb))
goto free_array;
if (unlikely(!bufb->buf_wsb))
goto free_array;
sizeof(struct lib_ring_buffer_backend_counts)
* num_subbuf,
1 << INTERNODE_CACHE_SHIFT),
sizeof(struct lib_ring_buffer_backend_counts)
* num_subbuf,
1 << INTERNODE_CACHE_SHIFT),
- GFP_KERNEL, cpu_to_node(max(bufb->cpu, 0)));
+ GFP_KERNEL | __GFP_NOWARN,
+ cpu_to_node(max(bufb->cpu, 0)));
if (unlikely(!bufb->buf_cnt))
goto free_wsb;
if (unlikely(!bufb->buf_cnt))
goto free_wsb;
* will not fault.
*/
wrapper_vmalloc_sync_all();
* will not fault.
*/
wrapper_vmalloc_sync_all();
__free_page(pages[i]);
kfree(bufb->array);
array_error:
__free_page(pages[i]);
kfree(bufb->array);
array_error:
pages_error:
return -ENOMEM;
}
pages_error:
return -ENOMEM;
}
kzalloc_node(ALIGN(sizeof(*buf->commit_hot)
* chan->backend.num_subbuf,
1 << INTERNODE_CACHE_SHIFT),
kzalloc_node(ALIGN(sizeof(*buf->commit_hot)
* chan->backend.num_subbuf,
1 << INTERNODE_CACHE_SHIFT),
- GFP_KERNEL, cpu_to_node(max(cpu, 0)));
+ GFP_KERNEL | __GFP_NOWARN,
+ cpu_to_node(max(cpu, 0)));
if (!buf->commit_hot) {
ret = -ENOMEM;
goto free_chanbuf;
if (!buf->commit_hot) {
ret = -ENOMEM;
goto free_chanbuf;
kzalloc_node(ALIGN(sizeof(*buf->commit_cold)
* chan->backend.num_subbuf,
1 << INTERNODE_CACHE_SHIFT),
kzalloc_node(ALIGN(sizeof(*buf->commit_cold)
* chan->backend.num_subbuf,
1 << INTERNODE_CACHE_SHIFT),
- GFP_KERNEL, cpu_to_node(max(cpu, 0)));
+ GFP_KERNEL | __GFP_NOWARN,
+ cpu_to_node(max(cpu, 0)));
if (!buf->commit_cold) {
ret = -ENOMEM;
goto free_commit;
if (!buf->commit_cold) {
ret = -ENOMEM;
goto free_commit;