Re: [PATCH v2 12/16] mm/slab: pass slab_alloc_context to __do_kmalloc_node()
From: Suren Baghdasaryan
Date: Mon Jun 15 2026 - 00:58:35 EST
On Wed, Jun 10, 2026 at 8:41 AM Vlastimil Babka (SUSE)
<vbabka@xxxxxxxxxx> wrote:
>
> With alloc_flags usage in slab, we can replace __GFP_NO_OBJ_EXT with an
> alloc flag that prevents kmalloc recursion. For that we need a version
> of kmalloc() that takes alloc_flags and use it in places that perform
> these potentially recursive kmalloc allocations (of sheaves or obj_ext
> arrays).
>
> As a preparatory step, make __do_kmalloc_node() take a pointer to
> slab_alloc_context. This replaces the 'caller' parameter and includes
> alloc_flags which we'll make use of.
I think you could also eliminate __do_kmalloc_node() function's "size"
parameter as it's always the same as ac->orig_size.
>
> Signed-off-by: Vlastimil Babka (SUSE) <vbabka@xxxxxxxxxx>
> ---
> mm/slub.c | 47 ++++++++++++++++++++++++++++++++---------------
> 1 file changed, 32 insertions(+), 15 deletions(-)
>
> diff --git a/mm/slub.c b/mm/slub.c
> index ef457e07db83..6845e15c148a 100644
> --- a/mm/slub.c
> +++ b/mm/slub.c
> @@ -5338,19 +5338,14 @@ EXPORT_SYMBOL(__kmalloc_large_node_noprof);
>
> static __always_inline
> void *__do_kmalloc_node(size_t size, kmem_buckets *b, gfp_t flags, int node,
> - unsigned long caller, kmalloc_token_t token)
> + kmalloc_token_t token, struct slab_alloc_context *ac)
> {
> struct kmem_cache *s;
> void *ret;
> - struct slab_alloc_context ac = {
> - .caller_addr = caller,
> - .orig_size = size,
> - .alloc_flags = SLAB_ALLOC_DEFAULT,
> - };
>
> if (unlikely(size > KMALLOC_MAX_CACHE_SIZE)) {
> ret = __kmalloc_large_node_noprof(size, flags, node);
> - trace_kmalloc(caller, ret, size,
> + trace_kmalloc(ac->caller_addr, ret, size,
> PAGE_SIZE << get_order(size), flags, node);
> return ret;
> }
> @@ -5360,22 +5355,34 @@ void *__do_kmalloc_node(size_t size, kmem_buckets *b, gfp_t flags, int node,
>
> s = kmalloc_slab(size, b, flags, token);
>
> - ret = slab_alloc_node(s, flags, node, &ac);
> + ret = slab_alloc_node(s, flags, node, ac);
> ret = kasan_kmalloc(s, ret, size, flags);
> - trace_kmalloc(caller, ret, size, s->size, flags, node);
> + trace_kmalloc(ac->caller_addr, ret, size, s->size, flags, node);
> return ret;
> }
> void *__kmalloc_node_noprof(DECL_KMALLOC_PARAMS(size, b, token), gfp_t flags, int node)
> {
> + struct slab_alloc_context ac = {
> + .caller_addr = _RET_IP_,
> + .orig_size = size,
> + .alloc_flags = SLAB_ALLOC_DEFAULT,
> + };
> +
> return __do_kmalloc_node(size, PASS_BUCKET_PARAM(b), flags, node,
> - _RET_IP_, PASS_TOKEN_PARAM(token));
> + PASS_TOKEN_PARAM(token), &ac);
> }
> EXPORT_SYMBOL(__kmalloc_node_noprof);
>
> void *__kmalloc_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t flags)
> {
> - return __do_kmalloc_node(size, NULL, flags, NUMA_NO_NODE, _RET_IP_,
> - PASS_TOKEN_PARAM(token));
> + struct slab_alloc_context ac = {
> + .caller_addr = _RET_IP_,
> + .orig_size = size,
> + .alloc_flags = SLAB_ALLOC_DEFAULT,
> + };
> +
> + return __do_kmalloc_node(size, NULL, flags, NUMA_NO_NODE,
> + PASS_TOKEN_PARAM(token), &ac);
> }
> EXPORT_SYMBOL(__kmalloc_noprof);
>
> @@ -5471,9 +5478,14 @@ EXPORT_SYMBOL_GPL(_kmalloc_nolock_noprof);
> void *__kmalloc_node_track_caller_noprof(DECL_KMALLOC_PARAMS(size, b, token), gfp_t flags,
> int node, unsigned long caller)
> {
> - return __do_kmalloc_node(size, PASS_BUCKET_PARAM(b), flags, node,
> - caller, PASS_TOKEN_PARAM(token));
> + struct slab_alloc_context ac = {
> + .caller_addr = caller,
> + .orig_size = size,
> + .alloc_flags = SLAB_ALLOC_DEFAULT,
> + };
>
> + return __do_kmalloc_node(size, PASS_BUCKET_PARAM(b), flags, node,
> + PASS_TOKEN_PARAM(token), &ac);
> }
> EXPORT_SYMBOL(__kmalloc_node_track_caller_noprof);
>
> @@ -6874,6 +6886,11 @@ void *__kvmalloc_node_noprof(DECL_KMALLOC_PARAMS(size, b, token), unsigned long
> {
> bool allow_block;
> void *ret;
> + struct slab_alloc_context ac = {
> + .caller_addr = _RET_IP_,
> + .orig_size = size,
> + .alloc_flags = SLAB_ALLOC_DEFAULT,
> + };
>
> /*
> * It doesn't really make sense to fallback to vmalloc for sub page
> @@ -6881,7 +6898,7 @@ void *__kvmalloc_node_noprof(DECL_KMALLOC_PARAMS(size, b, token), unsigned long
> */
> ret = __do_kmalloc_node(size, PASS_BUCKET_PARAM(b),
> kmalloc_gfp_adjust(flags, size),
> - node, _RET_IP_, PASS_TOKEN_PARAM(token));
> + node, PASS_TOKEN_PARAM(token), &ac);
> if (ret || size <= PAGE_SIZE)
> return ret;
>
>
> --
> 2.54.0
>