Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

kfifo: add kfifo_alloc_node() helper for NUMA awareness

Add __kfifo_alloc_node() by refactoring and reusing __kfifo_alloc(),
and define kfifo_alloc_node() macro to support NUMA-aware memory
allocation.

The new __kfifo_alloc_node() function accepts a NUMA node parameter
and uses kmalloc_array_node() instead of kmalloc_array() for
node-specific allocation. The existing __kfifo_alloc() now calls
__kfifo_alloc_node() with NUMA_NO_NODE to maintain backward
compatibility.

This enables users to allocate kfifo buffers on specific NUMA nodes,
which is important for performance in NUMA systems where the kfifo
will be primarily accessed by threads running on specific nodes.

Cc: Stefani Seibold <stefani@seibold.net>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ming Lei <ming.lei@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Ming Lei and committed by
Jens Axboe
9574b21e 89e1fb7c

+36 -6
+32 -2
include/linux/kfifo.h
··· 370 370 ) 371 371 372 372 /** 373 + * kfifo_alloc_node - dynamically allocates a new fifo buffer on a NUMA node 374 + * @fifo: pointer to the fifo 375 + * @size: the number of elements in the fifo, this must be a power of 2 376 + * @gfp_mask: get_free_pages mask, passed to kmalloc() 377 + * @node: NUMA node to allocate memory on 378 + * 379 + * This macro dynamically allocates a new fifo buffer with NUMA node awareness. 380 + * 381 + * The number of elements will be rounded-up to a power of 2. 382 + * The fifo will be release with kfifo_free(). 383 + * Return 0 if no error, otherwise an error code. 384 + */ 385 + #define kfifo_alloc_node(fifo, size, gfp_mask, node) \ 386 + __kfifo_int_must_check_helper( \ 387 + ({ \ 388 + typeof((fifo) + 1) __tmp = (fifo); \ 389 + struct __kfifo *__kfifo = &__tmp->kfifo; \ 390 + __is_kfifo_ptr(__tmp) ? \ 391 + __kfifo_alloc_node(__kfifo, size, sizeof(*__tmp->type), gfp_mask, node) : \ 392 + -EINVAL; \ 393 + }) \ 394 + ) 395 + 396 + /** 373 397 * kfifo_free - frees the fifo 374 398 * @fifo: the fifo to be freed 375 399 */ ··· 923 899 ) 924 900 925 901 926 - extern int __kfifo_alloc(struct __kfifo *fifo, unsigned int size, 927 - size_t esize, gfp_t gfp_mask); 902 + extern int __kfifo_alloc_node(struct __kfifo *fifo, unsigned int size, 903 + size_t esize, gfp_t gfp_mask, int node); 904 + 905 + static inline int __kfifo_alloc(struct __kfifo *fifo, unsigned int size, 906 + size_t esize, gfp_t gfp_mask) 907 + { 908 + return __kfifo_alloc_node(fifo, size, esize, gfp_mask, NUMA_NO_NODE); 909 + } 928 910 929 911 extern void __kfifo_free(struct __kfifo *fifo); 930 912
+4 -4
lib/kfifo.c
··· 22 22 return (fifo->mask + 1) - (fifo->in - fifo->out); 23 23 } 24 24 25 - int __kfifo_alloc(struct __kfifo *fifo, unsigned int size, 26 - size_t esize, gfp_t gfp_mask) 25 + int __kfifo_alloc_node(struct __kfifo *fifo, unsigned int size, 26 + size_t esize, gfp_t gfp_mask, int node) 27 27 { 28 28 /* 29 29 * round up to the next power of 2, since our 'let the indices ··· 41 41 return -EINVAL; 42 42 } 43 43 44 - fifo->data = kmalloc_array(esize, size, gfp_mask); 44 + fifo->data = kmalloc_array_node(esize, size, gfp_mask, node); 45 45 46 46 if (!fifo->data) { 47 47 fifo->mask = 0; ··· 51 51 52 52 return 0; 53 53 } 54 - EXPORT_SYMBOL(__kfifo_alloc); 54 + EXPORT_SYMBOL(__kfifo_alloc_node); 55 55 56 56 void __kfifo_free(struct __kfifo *fifo) 57 57 {