[PATCH V4 01/27] kfifo: add kfifo_alloc_node() helper for NUMA awareness

Ming Lei posted 27 patches 1 week, 4 days ago
[PATCH V4 01/27] kfifo: add kfifo_alloc_node() helper for NUMA awareness
Posted by Ming Lei 1 week, 4 days ago
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>
---
 include/linux/kfifo.h | 34 ++++++++++++++++++++++++++++++++--
 lib/kfifo.c           |  8 ++++----
 2 files changed, 36 insertions(+), 6 deletions(-)

diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h
index fd743d4c4b4b..8b81ac74829c 100644
--- a/include/linux/kfifo.h
+++ b/include/linux/kfifo.h
@@ -369,6 +369,30 @@ __kfifo_int_must_check_helper( \
 }) \
 )
 
+/**
+ * kfifo_alloc_node - dynamically allocates a new fifo buffer on a NUMA node
+ * @fifo: pointer to the fifo
+ * @size: the number of elements in the fifo, this must be a power of 2
+ * @gfp_mask: get_free_pages mask, passed to kmalloc()
+ * @node: NUMA node to allocate memory on
+ *
+ * This macro dynamically allocates a new fifo buffer with NUMA node awareness.
+ *
+ * The number of elements will be rounded-up to a power of 2.
+ * The fifo will be release with kfifo_free().
+ * Return 0 if no error, otherwise an error code.
+ */
+#define kfifo_alloc_node(fifo, size, gfp_mask, node) \
+__kfifo_int_must_check_helper( \
+({ \
+	typeof((fifo) + 1) __tmp = (fifo); \
+	struct __kfifo *__kfifo = &__tmp->kfifo; \
+	__is_kfifo_ptr(__tmp) ? \
+	__kfifo_alloc_node(__kfifo, size, sizeof(*__tmp->type), gfp_mask, node) : \
+	-EINVAL; \
+}) \
+)
+
 /**
  * kfifo_free - frees the fifo
  * @fifo: the fifo to be freed
@@ -899,8 +923,14 @@ __kfifo_uint_must_check_helper( \
 )
 
 
-extern int __kfifo_alloc(struct __kfifo *fifo, unsigned int size,
-	size_t esize, gfp_t gfp_mask);
+extern int __kfifo_alloc_node(struct __kfifo *fifo, unsigned int size,
+	size_t esize, gfp_t gfp_mask, int node);
+
+static inline int __kfifo_alloc(struct __kfifo *fifo, unsigned int size,
+				size_t esize, gfp_t gfp_mask)
+{
+	return __kfifo_alloc_node(fifo, size, esize, gfp_mask, NUMA_NO_NODE);
+}
 
 extern void __kfifo_free(struct __kfifo *fifo);
 
diff --git a/lib/kfifo.c b/lib/kfifo.c
index a8b2eed90599..525e66f8294c 100644
--- a/lib/kfifo.c
+++ b/lib/kfifo.c
@@ -22,8 +22,8 @@ static inline unsigned int kfifo_unused(struct __kfifo *fifo)
 	return (fifo->mask + 1) - (fifo->in - fifo->out);
 }
 
-int __kfifo_alloc(struct __kfifo *fifo, unsigned int size,
-		size_t esize, gfp_t gfp_mask)
+int __kfifo_alloc_node(struct __kfifo *fifo, unsigned int size,
+		size_t esize, gfp_t gfp_mask, int node)
 {
 	/*
 	 * round up to the next power of 2, since our 'let the indices
@@ -41,7 +41,7 @@ int __kfifo_alloc(struct __kfifo *fifo, unsigned int size,
 		return -EINVAL;
 	}
 
-	fifo->data = kmalloc_array(esize, size, gfp_mask);
+	fifo->data = kmalloc_array_node(esize, size, gfp_mask, node);
 
 	if (!fifo->data) {
 		fifo->mask = 0;
@@ -51,7 +51,7 @@ int __kfifo_alloc(struct __kfifo *fifo, unsigned int size,
 
 	return 0;
 }
-EXPORT_SYMBOL(__kfifo_alloc);
+EXPORT_SYMBOL(__kfifo_alloc_node);
 
 void __kfifo_free(struct __kfifo *fifo)
 {
-- 
2.47.0
Re: [PATCH V4 01/27] kfifo: add kfifo_alloc_node() helper for NUMA awareness
Posted by Caleb Sander Mateos 2 days, 6 hours ago
On Thu, Nov 20, 2025 at 5:59 PM Ming Lei <ming.lei@redhat.com> wrote:
>
> 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>
> ---
>  include/linux/kfifo.h | 34 ++++++++++++++++++++++++++++++++--
>  lib/kfifo.c           |  8 ++++----
>  2 files changed, 36 insertions(+), 6 deletions(-)
>
> diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h
> index fd743d4c4b4b..8b81ac74829c 100644
> --- a/include/linux/kfifo.h
> +++ b/include/linux/kfifo.h
> @@ -369,6 +369,30 @@ __kfifo_int_must_check_helper( \
>  }) \
>  )
>
> +/**
> + * kfifo_alloc_node - dynamically allocates a new fifo buffer on a NUMA node
> + * @fifo: pointer to the fifo
> + * @size: the number of elements in the fifo, this must be a power of 2
> + * @gfp_mask: get_free_pages mask, passed to kmalloc()
> + * @node: NUMA node to allocate memory on
> + *
> + * This macro dynamically allocates a new fifo buffer with NUMA node awareness.
> + *
> + * The number of elements will be rounded-up to a power of 2.
> + * The fifo will be release with kfifo_free().
> + * Return 0 if no error, otherwise an error code.
> + */
> +#define kfifo_alloc_node(fifo, size, gfp_mask, node) \
> +__kfifo_int_must_check_helper( \
> +({ \
> +       typeof((fifo) + 1) __tmp = (fifo); \
> +       struct __kfifo *__kfifo = &__tmp->kfifo; \
> +       __is_kfifo_ptr(__tmp) ? \
> +       __kfifo_alloc_node(__kfifo, size, sizeof(*__tmp->type), gfp_mask, node) : \
> +       -EINVAL; \
> +}) \
> +)

Looks like we could avoid some code duplication by defining
kfifo_alloc(fifo, size, gfp_mask) as kfifo_alloc_node(fifo, size,
gfp_mask, NUMA_NO_NODE). Otherwise, this looks good to me.

Best,
Caleb

> +
>  /**
>   * kfifo_free - frees the fifo
>   * @fifo: the fifo to be freed
> @@ -899,8 +923,14 @@ __kfifo_uint_must_check_helper( \
>  )
>
>
> -extern int __kfifo_alloc(struct __kfifo *fifo, unsigned int size,
> -       size_t esize, gfp_t gfp_mask);
> +extern int __kfifo_alloc_node(struct __kfifo *fifo, unsigned int size,
> +       size_t esize, gfp_t gfp_mask, int node);
> +
> +static inline int __kfifo_alloc(struct __kfifo *fifo, unsigned int size,
> +                               size_t esize, gfp_t gfp_mask)
> +{
> +       return __kfifo_alloc_node(fifo, size, esize, gfp_mask, NUMA_NO_NODE);
> +}
>
>  extern void __kfifo_free(struct __kfifo *fifo);
>
> diff --git a/lib/kfifo.c b/lib/kfifo.c
> index a8b2eed90599..525e66f8294c 100644
> --- a/lib/kfifo.c
> +++ b/lib/kfifo.c
> @@ -22,8 +22,8 @@ static inline unsigned int kfifo_unused(struct __kfifo *fifo)
>         return (fifo->mask + 1) - (fifo->in - fifo->out);
>  }
>
> -int __kfifo_alloc(struct __kfifo *fifo, unsigned int size,
> -               size_t esize, gfp_t gfp_mask)
> +int __kfifo_alloc_node(struct __kfifo *fifo, unsigned int size,
> +               size_t esize, gfp_t gfp_mask, int node)
>  {
>         /*
>          * round up to the next power of 2, since our 'let the indices
> @@ -41,7 +41,7 @@ int __kfifo_alloc(struct __kfifo *fifo, unsigned int size,
>                 return -EINVAL;
>         }
>
> -       fifo->data = kmalloc_array(esize, size, gfp_mask);
> +       fifo->data = kmalloc_array_node(esize, size, gfp_mask, node);
>
>         if (!fifo->data) {
>                 fifo->mask = 0;
> @@ -51,7 +51,7 @@ int __kfifo_alloc(struct __kfifo *fifo, unsigned int size,
>
>         return 0;
>  }
> -EXPORT_SYMBOL(__kfifo_alloc);
> +EXPORT_SYMBOL(__kfifo_alloc_node);
>
>  void __kfifo_free(struct __kfifo *fifo)
>  {
> --
> 2.47.0
>
Re: [PATCH V4 01/27] kfifo: add kfifo_alloc_node() helper for NUMA awareness
Posted by Ming Lei 1 day ago
On Sat, Nov 29, 2025 at 11:12:43AM -0800, Caleb Sander Mateos wrote:
> On Thu, Nov 20, 2025 at 5:59 PM Ming Lei <ming.lei@redhat.com> wrote:
> >
> > 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>
> > ---
> >  include/linux/kfifo.h | 34 ++++++++++++++++++++++++++++++++--
> >  lib/kfifo.c           |  8 ++++----
> >  2 files changed, 36 insertions(+), 6 deletions(-)
> >
> > diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h
> > index fd743d4c4b4b..8b81ac74829c 100644
> > --- a/include/linux/kfifo.h
> > +++ b/include/linux/kfifo.h
> > @@ -369,6 +369,30 @@ __kfifo_int_must_check_helper( \
> >  }) \
> >  )
> >
> > +/**
> > + * kfifo_alloc_node - dynamically allocates a new fifo buffer on a NUMA node
> > + * @fifo: pointer to the fifo
> > + * @size: the number of elements in the fifo, this must be a power of 2
> > + * @gfp_mask: get_free_pages mask, passed to kmalloc()
> > + * @node: NUMA node to allocate memory on
> > + *
> > + * This macro dynamically allocates a new fifo buffer with NUMA node awareness.
> > + *
> > + * The number of elements will be rounded-up to a power of 2.
> > + * The fifo will be release with kfifo_free().
> > + * Return 0 if no error, otherwise an error code.
> > + */
> > +#define kfifo_alloc_node(fifo, size, gfp_mask, node) \
> > +__kfifo_int_must_check_helper( \
> > +({ \
> > +       typeof((fifo) + 1) __tmp = (fifo); \
> > +       struct __kfifo *__kfifo = &__tmp->kfifo; \
> > +       __is_kfifo_ptr(__tmp) ? \
> > +       __kfifo_alloc_node(__kfifo, size, sizeof(*__tmp->type), gfp_mask, node) : \
> > +       -EINVAL; \
> > +}) \
> > +)
> 
> Looks like we could avoid some code duplication by defining
> kfifo_alloc(fifo, size, gfp_mask) as kfifo_alloc_node(fifo, size,
> gfp_mask, NUMA_NO_NODE). Otherwise, this looks good to me.

It is just a single-line inline, and shouldn't introduce any code
duplication. Switching to kfifo_alloc_node() doesn't change result of
`size vmlinux` actually.



Thanks,
Ming

Re: [PATCH V4 01/27] kfifo: add kfifo_alloc_node() helper for NUMA awareness
Posted by Caleb Sander Mateos 20 hours ago
On Sun, Nov 30, 2025 at 5:46 PM Ming Lei <ming.lei@redhat.com> wrote:
>
> On Sat, Nov 29, 2025 at 11:12:43AM -0800, Caleb Sander Mateos wrote:
> > On Thu, Nov 20, 2025 at 5:59 PM Ming Lei <ming.lei@redhat.com> wrote:
> > >
> > > 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>
> > > ---
> > >  include/linux/kfifo.h | 34 ++++++++++++++++++++++++++++++++--
> > >  lib/kfifo.c           |  8 ++++----
> > >  2 files changed, 36 insertions(+), 6 deletions(-)
> > >
> > > diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h
> > > index fd743d4c4b4b..8b81ac74829c 100644
> > > --- a/include/linux/kfifo.h
> > > +++ b/include/linux/kfifo.h
> > > @@ -369,6 +369,30 @@ __kfifo_int_must_check_helper( \
> > >  }) \
> > >  )
> > >
> > > +/**
> > > + * kfifo_alloc_node - dynamically allocates a new fifo buffer on a NUMA node
> > > + * @fifo: pointer to the fifo
> > > + * @size: the number of elements in the fifo, this must be a power of 2
> > > + * @gfp_mask: get_free_pages mask, passed to kmalloc()
> > > + * @node: NUMA node to allocate memory on
> > > + *
> > > + * This macro dynamically allocates a new fifo buffer with NUMA node awareness.
> > > + *
> > > + * The number of elements will be rounded-up to a power of 2.
> > > + * The fifo will be release with kfifo_free().
> > > + * Return 0 if no error, otherwise an error code.
> > > + */
> > > +#define kfifo_alloc_node(fifo, size, gfp_mask, node) \
> > > +__kfifo_int_must_check_helper( \
> > > +({ \
> > > +       typeof((fifo) + 1) __tmp = (fifo); \
> > > +       struct __kfifo *__kfifo = &__tmp->kfifo; \
> > > +       __is_kfifo_ptr(__tmp) ? \
> > > +       __kfifo_alloc_node(__kfifo, size, sizeof(*__tmp->type), gfp_mask, node) : \
> > > +       -EINVAL; \
> > > +}) \
> > > +)
> >
> > Looks like we could avoid some code duplication by defining
> > kfifo_alloc(fifo, size, gfp_mask) as kfifo_alloc_node(fifo, size,
> > gfp_mask, NUMA_NO_NODE). Otherwise, this looks good to me.
>
> It is just a single-line inline, and shouldn't introduce any code
> duplication. Switching to kfifo_alloc_node() doesn't change result of
> `size vmlinux` actually.

Right, I know they expand to the same thing. I'm just saying we can
avoid repeating the nearly identical implementations by writing
kfifo_alloc() in terms of kfifo_alloc_node().

Best,
Caleb