]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
mm/slab: pass slab_alloc_context to __do_kmalloc_node()
authorVlastimil Babka (SUSE) <vbabka@kernel.org>
Wed, 10 Jun 2026 15:40:14 +0000 (17:40 +0200)
committerVlastimil Babka (SUSE) <vbabka@kernel.org>
Mon, 15 Jun 2026 11:26:27 +0000 (13:26 +0200)
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 'size' and 'caller' parameters and
includes alloc_flags which we'll make use of.

Link: https://patch.msgid.link/20260610-slab_alloc_flags-v2-12-7190909db118@kernel.org
Reviewed-by: Hao Li <hao.li@linux.dev>
Reviewed-by: Harry Yoo (Oracle) <harry@kernel.org>
Reviewed-by: Suren Baghdasaryan <surenb@google.com>
Signed-off-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
mm/slub.c

index 81938774098b51af6a3d25e648ecec0a5c56f553..537ea68f417b40cd56d79722e7bd044a963b5ad7 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -5335,20 +5335,16 @@ void *__kmalloc_large_node_noprof(size_t size, gfp_t flags, int node)
 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)
+void *__do_kmalloc_node(kmem_buckets *b, gfp_t flags, int node,
+                       kmalloc_token_t token, const struct slab_alloc_context *ac)
 {
+       const size_t size = ac->orig_size;
        struct kmem_cache *s;
        void *ret;
-       const 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;
        }
@@ -5358,22 +5354,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)
 {
-       return __do_kmalloc_node(size, PASS_BUCKET_PARAM(b), flags, node,
-                                _RET_IP_, PASS_TOKEN_PARAM(token));
+       const struct slab_alloc_context ac = {
+               .caller_addr = _RET_IP_,
+               .orig_size = size,
+               .alloc_flags = SLAB_ALLOC_DEFAULT,
+       };
+
+       return __do_kmalloc_node(PASS_BUCKET_PARAM(b), flags, node,
+                                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));
+       const struct slab_alloc_context ac = {
+               .caller_addr = _RET_IP_,
+               .orig_size = size,
+               .alloc_flags = SLAB_ALLOC_DEFAULT,
+       };
+
+       return __do_kmalloc_node(NULL, flags,  NUMA_NO_NODE,
+                                PASS_TOKEN_PARAM(token), &ac);
 }
 EXPORT_SYMBOL(__kmalloc_noprof);
 
@@ -5468,9 +5476,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));
+       const struct slab_alloc_context ac = {
+               .caller_addr = caller,
+               .orig_size = size,
+               .alloc_flags = SLAB_ALLOC_DEFAULT,
+       };
 
+       return __do_kmalloc_node(PASS_BUCKET_PARAM(b), flags, node,
+                                PASS_TOKEN_PARAM(token), &ac);
 }
 EXPORT_SYMBOL(__kmalloc_node_track_caller_noprof);
 
@@ -6871,14 +6884,19 @@ void *__kvmalloc_node_noprof(DECL_KMALLOC_PARAMS(size, b, token), unsigned long
 {
        bool allow_block;
        void *ret;
+       const 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
         * requests
         */
-       ret = __do_kmalloc_node(size, PASS_BUCKET_PARAM(b),
+       ret = __do_kmalloc_node(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;