mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* Re: [PATCH v2 13/16] mm/slab: allow __GFP_NOMEMALLOC and __GFP_NOWARN for kmalloc_nolock()
@ 2026-06-12 12:52 hu.shengming
  2026-06-12 13:00 ` Vlastimil Babka (SUSE)
  0 siblings, 1 reply; 6+ messages in thread
From: hu.shengming @ 2026-06-12 12:52 UTC (permalink / raw)
  To: vbabka
  Cc: harry, akpm, hao.li, cl, rientjes, roman.gushchin, linux-mm,
	linux-kernel, zhang.run, cai.qu

Vlastimil Babka (SUSE) wrote:
> The two flags are added internally so there's no point for warning if
> they are passed by the caller as well, so allow them. This will allow
> simplifying obj_ext allocation under kmalloc_nolock().
> 
> Also it's not necessary to have the extra alloc_gfp variable for adding
> the two flags. The original gfp_flags parameter is not used anywhere
> except for the warning. So remove alloc_gfp and directly modify and use
> gfp_flags everywhere.
> 
> Signed-off-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
> ---
>  include/linux/slab.h |  3 ++-
>  mm/slub.c            | 19 ++++++++++---------
>  2 files changed, 12 insertions(+), 10 deletions(-)
> 
> diff --git a/include/linux/slab.h b/include/linux/slab.h
> index ce1c867dc0ba..b955f3cbb732 100644
> --- a/include/linux/slab.h
> +++ b/include/linux/slab.h
> @@ -1040,7 +1040,8 @@ void *_kmalloc_nolock_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t gfp_flags, in
>   * kmalloc_nolock - Allocate an object of given size from any context.
>   * @size: size to allocate
>   * @gfp_flags: GFP flags. Only __GFP_ACCOUNT, __GFP_ZERO, __GFP_NO_OBJ_EXT
> - * allowed.
> + * allowed. Also __GFP_NOWARN and __GFP_NOMEMALLOC are allowed but added
> + * internally thus not necessary.
>   * @node: node number of the target node.
>   *
>   * Return: pointer to the new object or NULL in case of error.
> diff --git a/mm/slub.c b/mm/slub.c
> index 6845e15c148a..847cad5203b2 100644
> --- a/mm/slub.c
> +++ b/mm/slub.c
> @@ -5388,7 +5388,6 @@ EXPORT_SYMBOL(__kmalloc_noprof);
>  
>  void *_kmalloc_nolock_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t gfp_flags, int node)
>  {
> -	gfp_t alloc_gfp = __GFP_NOWARN | __GFP_NOMEMALLOC | gfp_flags;
>  	size_t orig_size = size;
>  	unsigned int alloc_flags = SLAB_ALLOC_TRYLOCK;
>  	struct kmem_cache *s;
> @@ -5396,7 +5395,9 @@ void *_kmalloc_nolock_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t gfp_flags, in
>  	void *ret;
>  
>  	VM_WARN_ON_ONCE(gfp_flags & ~(__GFP_ACCOUNT | __GFP_ZERO |
> -				      __GFP_NO_OBJ_EXT));
> +			__GFP_NO_OBJ_EXT | __GFP_NOWARN | __GFP_NOMEMALLOC));
> +
> +	gfp_flags |= __GFP_NOWARN | __GFP_NOMEMALLOC;
>  

Hi Vlastimil,

While reviewing your patch, I spotted a potential GFP flag mismatch along the kmalloc_flags()
-> __kmalloc_nolock_noprof() call path. I cloned the slab/for-next branch to verify this and
successfully triggered a VM_WARN_ON_ONCE() in the __kmalloc_nolock_noprof() path.

Here is the observed trace:

[   57.283791] ------------[ cut here ]------------
[   57.284226] WARNING: mm/slub.c:5407 at __kmalloc_nolock_noprof+0x3ec/0x450, CPU#6: insmod/379
[   57.285060] Modules linked in: slub_nolock(O+)
[   57.285494] CPU: 6 UID: 0 PID: 379 Comm: insmod Tainted: G           O        7.1.0-rc3-00036-g5ade53586fae-dirty #5 PREEMPT(lazy) 
[   57.286608] Tainted: [O]=OOT_MODULE
[   57.286941] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.1-0-ga5cab58e9a3f-prebuilt.qemu.org 04/01/2014
[   57.288018] RIP: 0010:__kmalloc_nolock_noprof+0x3ec/0x450
[   57.288543] Code: 01 00 8b 4c 24 04 41 89 c2 e9 dd fc ff ff b8 10 00 00 00 e9 f9 fd ff ff 90 0f 0b 90 f7 04 24 ff de b7 ff 0f 84 54
[   57.290252] RSP: 0018:ffffa82840c73b68 EFLAGS: 00010206
[   57.290752] RAX: 0000000000000000 RBX: 0000000000000003 RCX: ffffa82840c73bc8
[   57.291428] RDX: 0000000000000000 RSI: 00000000002c2100 RDI: 0000000000000100
[   57.292124] RBP: 0000000000000000 R08: ffffffffb853c968 R09: 0000000000009ffb
[   57.292821] R10: 00000000000001d7 R11: ffffffffb850c980 R12: 00000000002c2100
[   57.293485] R13: 0000000000000000 R14: ffffa82840c73bc8 R15: 0000000000000003
[   57.294159] FS:  0000000006fa8880(0000) GS:ffff8f4ef9d5a000(0000) knlGS:0000000000000000
[   57.294914] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   57.295464] CR2: 0000000006fac528 CR3: 000000003f9b6003 CR4: 0000000000770ef0
[   57.296124] PKRU: 55555554
[   57.296443] Call Trace:
[   57.296702]  <TASK>
[   57.296914]  ? vprintk_emit+0x22e/0x280
[   57.297295]  __kmalloc_flags_noprof+0x216/0x530
[   57.297735]  ? _printk+0x56/0x70
[   57.298053]  ? alloc_slab_obj_exts+0x89/0x1e0
[   57.298474]  alloc_slab_obj_exts+0x89/0x1e0
[   57.298876]  new_slab+0x2bc/0x660
[   57.299200]  ___slab_alloc+0x2ae/0x660
[   57.299603]  __kmalloc_nolock_noprof+0x151/0x450
[   57.300050]  _kmalloc_nolock_noprof+0x47/0x70
[   57.300490]  ? slub_nolock_init+0x127/0xff0 [slub_nolock]
[   57.301013]  slub_nolock_init+0x127/0xff0 [slub_nolock]
[   57.301566]  ? __pfx_slub_nolock_init+0x10/0x10 [slub_nolock]
[   57.302197]  do_one_initcall+0x44/0x220
[   57.302598]  ? do_init_module+0x1e/0x240
[   57.302990]  do_init_module+0x5f/0x240
[   57.303357]  __do_sys_init_module+0x162/0x190
[   57.303783]  do_syscall_64+0xf7/0x550
[   57.304159]  entry_SYSCALL_64_after_hwframe+0x77/0x7f
[   57.304648] RIP: 0033:0x4b8839
[   57.304954] Code: 00 f3 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 40
[   57.306676] RSP: 002b:00007ffea38fdce8 EFLAGS: 00000246 ORIG_RAX: 00000000000000af
[   57.307376] RAX: ffffffffffffffda RBX: 00007ffea38fe080 RCX: 00000000004b8839
[   57.308044] RDX: 000000000062d4b5 RSI: 0000000000002790 RDI: 0000000006fa9d20
[   57.308710] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000002790
[   57.309366] R10: 0000000006fa9cc0 R11: 0000000000000246 R12: 00007ffea38fe088
[   57.310040] R13: 000000000062d4b5 R14: 0000000000000000 R15: 0000000000000000
[   57.310737]  </TASK>
[   57.310963] ---[ end trace 0000000000000000 ]---

With "# CONFIG_KMALLOC_PARTITION_CACHES is not set":
RSI: 00000000002c2100 -> gfp_flags

Decoding the GFP bits:

  0x00000100 = __GFP_ZERO
  0x00002000 = __GFP_NOWARN
  0x00080000 = __GFP_NOMEMALLOC
  0x00040000 = __GFP_COMP
  0x00200000 = __GFP_THISNODE

The root cause:

Previously, the obj_ext allocation path(alloc_slab_obj_exts()) called kmalloc_nolock() with a
fixed set of flags(__GFP_ZERO | __GFP_NO_OBJ_EXT). After switching to kmalloc_flags(), the
full GFP mask from the upper allocation path propagates through the call chain.

In detail, ___slab_alloc() may append __GFP_THISNODE, and allocate_slab() adds __GFP_COMP
via s->allocflags. Both flags flow down unchanged into __kmalloc_nolock_noprof().

This patch only permits four flags (__GFP_ACCOUNT, __GFP_ZERO, __GFP_NOWARN and __GFP_NOMEMALLOC).
Since neither __GFP_THISNODE nor __GFP_COMP is in the allowed set, the warning is triggered.

Would the following fix be acceptable?

    +#define KMALLOC_NOLOCK_ALLOWED_GFP \
    +       (__GFP_ACCOUNT | __GFP_ZERO | __GFP_NOWARN | __GFP_NOMEMALLOC)
    +
    /*
    * The only version of kmalloc_node() that takes alloc_flags and thus can
    * determine on its own whether to handle the allocation via kmalloc_nolock() or
    @@ -5548,6 +5564,7 @@ void *__kmalloc_flags_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t flags,
                    return __do_kmalloc_node(size, NULL, flags, node,
                                    PASS_TOKEN_PARAM(token), &ac);
            } else {
    +               flags &= KMALLOC_NOLOCK_ALLOWED_GFP;
                    return __kmalloc_nolock_noprof(PASS_TOKEN_PARAMS(size, token),
                                                flags, node, &ac);
            }

--
With Best Regards,
Shengming

>  	if (unlikely(!size))
>  		return ZERO_SIZE_PTR;
> @@ -5415,7 +5416,7 @@ void *_kmalloc_nolock_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t gfp_flags, in
>  retry:
>  	if (unlikely(size > KMALLOC_MAX_CACHE_SIZE))
>  		return NULL;
> -	s = kmalloc_slab(size, NULL, alloc_gfp, PASS_TOKEN_PARAM(token));
> +	s = kmalloc_slab(size, NULL, gfp_flags, PASS_TOKEN_PARAM(token));
>  
>  	if (!(s->flags & __CMPXCHG_DOUBLE) && !kmem_cache_debug(s))
>  		/*
> @@ -5429,7 +5430,7 @@ void *_kmalloc_nolock_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t gfp_flags, in
>  		 */
>  		return NULL;
>  
> -	ret = alloc_from_pcs(s, alloc_gfp, alloc_flags, node);
> +	ret = alloc_from_pcs(s, gfp_flags, alloc_flags, node);
>  	if (ret)
>  		goto success;
>  
> @@ -5445,7 +5446,7 @@ void *_kmalloc_nolock_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t gfp_flags, in
>  	 * kfence_alloc. Hence call __slab_alloc_node() (at most twice)
>  	 * and slab_post_alloc_hook() directly.
>  	 */
> -	ret = __slab_alloc_node(s, alloc_gfp, node, &ac);
> +	ret = __slab_alloc_node(s, gfp_flags, node, &ac);
>  
>  	/*
>  	 * It's possible we failed due to trylock as we preempted someone with
> @@ -5458,8 +5459,8 @@ void *_kmalloc_nolock_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t gfp_flags, in
>  		size = s->object_size + 1;
>  		/*
>  		 * Another alternative is to
> -		 * if (memcg) alloc_gfp &= ~__GFP_ACCOUNT;
> -		 * else if (!memcg) alloc_gfp |= __GFP_ACCOUNT;
> +		 * if (memcg) gfp_flags &= ~__GFP_ACCOUNT;
> +		 * else if (!memcg) gfp_flags |= __GFP_ACCOUNT;
>  		 * to retry from bucket of the same size.
>  		 */
>  		can_retry = false;
> @@ -5468,9 +5469,9 @@ void *_kmalloc_nolock_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t gfp_flags, in
>  
>  success:
>  	maybe_wipe_obj_freeptr(s, ret);
> -	slab_post_alloc_hook(s, alloc_gfp, 1, &ret, &ac);
> +	slab_post_alloc_hook(s, gfp_flags, 1, &ret, &ac);
>  
> -	ret = kasan_kmalloc(s, ret, orig_size, alloc_gfp);
> +	ret = kasan_kmalloc(s, ret, orig_size, gfp_flags);
>  	return ret;
>  }
>  EXPORT_SYMBOL_GPL(_kmalloc_nolock_noprof);
> 
> -- 
> 2.54.0
>

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 13/16] mm/slab: allow __GFP_NOMEMALLOC and __GFP_NOWARN for kmalloc_nolock()
  2026-06-12 12:52 [PATCH v2 13/16] mm/slab: allow __GFP_NOMEMALLOC and __GFP_NOWARN for kmalloc_nolock() hu.shengming
@ 2026-06-12 13:00 ` Vlastimil Babka (SUSE)
  2026-06-12 13:14   ` hu.shengming
  0 siblings, 1 reply; 6+ messages in thread
From: Vlastimil Babka (SUSE) @ 2026-06-12 13:00 UTC (permalink / raw)
  To: hu.shengming
  Cc: harry, akpm, hao.li, cl, rientjes, roman.gushchin, linux-mm,
	linux-kernel, zhang.run, cai.qu

On 6/12/26 14:52, hu.shengming@zte.com.cn wrote:
> Vlastimil Babka (SUSE) wrote:
>> The two flags are added internally so there's no point for warning if
>> they are passed by the caller as well, so allow them. This will allow
>> simplifying obj_ext allocation under kmalloc_nolock().
>> 
>> Also it's not necessary to have the extra alloc_gfp variable for adding
>> the two flags. The original gfp_flags parameter is not used anywhere
>> except for the warning. So remove alloc_gfp and directly modify and use
>> gfp_flags everywhere.
>> 
>> Signed-off-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
>> ---
>>  include/linux/slab.h |  3 ++-
>>  mm/slub.c            | 19 ++++++++++---------
>>  2 files changed, 12 insertions(+), 10 deletions(-)
>> 
>> diff --git a/include/linux/slab.h b/include/linux/slab.h
>> index ce1c867dc0ba..b955f3cbb732 100644
>> --- a/include/linux/slab.h
>> +++ b/include/linux/slab.h
>> @@ -1040,7 +1040,8 @@ void *_kmalloc_nolock_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t gfp_flags, in
>>   * kmalloc_nolock - Allocate an object of given size from any context.
>>   * @size: size to allocate
>>   * @gfp_flags: GFP flags. Only __GFP_ACCOUNT, __GFP_ZERO, __GFP_NO_OBJ_EXT
>> - * allowed.
>> + * allowed. Also __GFP_NOWARN and __GFP_NOMEMALLOC are allowed but added
>> + * internally thus not necessary.
>>   * @node: node number of the target node.
>>   *
>>   * Return: pointer to the new object or NULL in case of error.
>> diff --git a/mm/slub.c b/mm/slub.c
>> index 6845e15c148a..847cad5203b2 100644
>> --- a/mm/slub.c
>> +++ b/mm/slub.c
>> @@ -5388,7 +5388,6 @@ EXPORT_SYMBOL(__kmalloc_noprof);
>>  
>>  void *_kmalloc_nolock_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t gfp_flags, int node)
>>  {
>> -	gfp_t alloc_gfp = __GFP_NOWARN | __GFP_NOMEMALLOC | gfp_flags;
>>  	size_t orig_size = size;
>>  	unsigned int alloc_flags = SLAB_ALLOC_TRYLOCK;
>>  	struct kmem_cache *s;
>> @@ -5396,7 +5395,9 @@ void *_kmalloc_nolock_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t gfp_flags, in
>>  	void *ret;
>>  
>>  	VM_WARN_ON_ONCE(gfp_flags & ~(__GFP_ACCOUNT | __GFP_ZERO |
>> -				      __GFP_NO_OBJ_EXT));
>> +			__GFP_NO_OBJ_EXT | __GFP_NOWARN | __GFP_NOMEMALLOC));
>> +
>> +	gfp_flags |= __GFP_NOWARN | __GFP_NOMEMALLOC;
>>  
> 
> Hi Vlastimil,
> 
> While reviewing your patch, I spotted a potential GFP flag mismatch along the kmalloc_flags()
> -> __kmalloc_nolock_noprof() call path. I cloned the slab/for-next branch to verify this and
> successfully triggered a VM_WARN_ON_ONCE() in the __kmalloc_nolock_noprof() path.
> 
> Here is the observed trace:
> 
> [   57.283791] ------------[ cut here ]------------
> [   57.284226] WARNING: mm/slub.c:5407 at __kmalloc_nolock_noprof+0x3ec/0x450, CPU#6: insmod/379
> [   57.285060] Modules linked in: slub_nolock(O+)
> [   57.285494] CPU: 6 UID: 0 PID: 379 Comm: insmod Tainted: G           O        7.1.0-rc3-00036-g5ade53586fae-dirty #5 PREEMPT(lazy) 
> [   57.286608] Tainted: [O]=OOT_MODULE
> [   57.286941] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.1-0-ga5cab58e9a3f-prebuilt.qemu.org 04/01/2014
> [   57.288018] RIP: 0010:__kmalloc_nolock_noprof+0x3ec/0x450
> [   57.288543] Code: 01 00 8b 4c 24 04 41 89 c2 e9 dd fc ff ff b8 10 00 00 00 e9 f9 fd ff ff 90 0f 0b 90 f7 04 24 ff de b7 ff 0f 84 54
> [   57.290252] RSP: 0018:ffffa82840c73b68 EFLAGS: 00010206
> [   57.290752] RAX: 0000000000000000 RBX: 0000000000000003 RCX: ffffa82840c73bc8
> [   57.291428] RDX: 0000000000000000 RSI: 00000000002c2100 RDI: 0000000000000100
> [   57.292124] RBP: 0000000000000000 R08: ffffffffb853c968 R09: 0000000000009ffb
> [   57.292821] R10: 00000000000001d7 R11: ffffffffb850c980 R12: 00000000002c2100
> [   57.293485] R13: 0000000000000000 R14: ffffa82840c73bc8 R15: 0000000000000003
> [   57.294159] FS:  0000000006fa8880(0000) GS:ffff8f4ef9d5a000(0000) knlGS:0000000000000000
> [   57.294914] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [   57.295464] CR2: 0000000006fac528 CR3: 000000003f9b6003 CR4: 0000000000770ef0
> [   57.296124] PKRU: 55555554
> [   57.296443] Call Trace:
> [   57.296702]  <TASK>
> [   57.296914]  ? vprintk_emit+0x22e/0x280
> [   57.297295]  __kmalloc_flags_noprof+0x216/0x530
> [   57.297735]  ? _printk+0x56/0x70
> [   57.298053]  ? alloc_slab_obj_exts+0x89/0x1e0
> [   57.298474]  alloc_slab_obj_exts+0x89/0x1e0
> [   57.298876]  new_slab+0x2bc/0x660
> [   57.299200]  ___slab_alloc+0x2ae/0x660
> [   57.299603]  __kmalloc_nolock_noprof+0x151/0x450
> [   57.300050]  _kmalloc_nolock_noprof+0x47/0x70
> [   57.300490]  ? slub_nolock_init+0x127/0xff0 [slub_nolock]
> [   57.301013]  slub_nolock_init+0x127/0xff0 [slub_nolock]
> [   57.301566]  ? __pfx_slub_nolock_init+0x10/0x10 [slub_nolock]
> [   57.302197]  do_one_initcall+0x44/0x220
> [   57.302598]  ? do_init_module+0x1e/0x240
> [   57.302990]  do_init_module+0x5f/0x240
> [   57.303357]  __do_sys_init_module+0x162/0x190
> [   57.303783]  do_syscall_64+0xf7/0x550
> [   57.304159]  entry_SYSCALL_64_after_hwframe+0x77/0x7f
> [   57.304648] RIP: 0033:0x4b8839
> [   57.304954] Code: 00 f3 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 40
> [   57.306676] RSP: 002b:00007ffea38fdce8 EFLAGS: 00000246 ORIG_RAX: 00000000000000af
> [   57.307376] RAX: ffffffffffffffda RBX: 00007ffea38fe080 RCX: 00000000004b8839
> [   57.308044] RDX: 000000000062d4b5 RSI: 0000000000002790 RDI: 0000000006fa9d20
> [   57.308710] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000002790
> [   57.309366] R10: 0000000006fa9cc0 R11: 0000000000000246 R12: 00007ffea38fe088
> [   57.310040] R13: 000000000062d4b5 R14: 0000000000000000 R15: 0000000000000000
> [   57.310737]  </TASK>
> [   57.310963] ---[ end trace 0000000000000000 ]---
> 
> With "# CONFIG_KMALLOC_PARTITION_CACHES is not set":
> RSI: 00000000002c2100 -> gfp_flags
> 
> Decoding the GFP bits:
> 
>   0x00000100 = __GFP_ZERO
>   0x00002000 = __GFP_NOWARN
>   0x00080000 = __GFP_NOMEMALLOC
>   0x00040000 = __GFP_COMP
>   0x00200000 = __GFP_THISNODE
> 
> The root cause:
> 
> Previously, the obj_ext allocation path(alloc_slab_obj_exts()) called kmalloc_nolock() with a
> fixed set of flags(__GFP_ZERO | __GFP_NO_OBJ_EXT). After switching to kmalloc_flags(), the
> full GFP mask from the upper allocation path propagates through the call chain.
> 
> In detail, ___slab_alloc() may append __GFP_THISNODE, and allocate_slab() adds __GFP_COMP
> via s->allocflags. Both flags flow down unchanged into __kmalloc_nolock_noprof().
> 
> This patch only permits four flags (__GFP_ACCOUNT, __GFP_ZERO, __GFP_NOWARN and __GFP_NOMEMALLOC).
> Since neither __GFP_THISNODE nor __GFP_COMP is in the allowed set, the warning is triggered.
> 
> Would the following fix be acceptable?
> 
>     +#define KMALLOC_NOLOCK_ALLOWED_GFP \
>     +       (__GFP_ACCOUNT | __GFP_ZERO | __GFP_NOWARN | __GFP_NOMEMALLOC)
>     +
>     /*
>     * The only version of kmalloc_node() that takes alloc_flags and thus can
>     * determine on its own whether to handle the allocation via kmalloc_nolock() or
>     @@ -5548,6 +5564,7 @@ void *__kmalloc_flags_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t flags,
>                     return __do_kmalloc_node(size, NULL, flags, node,
>                                     PASS_TOKEN_PARAM(token), &ac);
>             } else {
>     +               flags &= KMALLOC_NOLOCK_ALLOWED_GFP;
>                     return __kmalloc_nolock_noprof(PASS_TOKEN_PARAMS(size, token),
>                                                 flags, node, &ac);
>             }

Thanks, Hao Li pointed out __GFP_THISNODE and I filtered it from nested
allocations like this:
https://lore.kernel.org/all/49f1bf1e-fcaf-48fa-a7b1-f8ee78b19762@kernel.org/
It makes sense to filter out __GFP_COMP too as that's a page allocator flag
and not useful for (nested) kmalloc allocations, so I'll add that



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 13/16] mm/slab: allow __GFP_NOMEMALLOC and __GFP_NOWARN for kmalloc_nolock()
  2026-06-12 13:00 ` Vlastimil Babka (SUSE)
@ 2026-06-12 13:14   ` hu.shengming
  0 siblings, 0 replies; 6+ messages in thread
From: hu.shengming @ 2026-06-12 13:14 UTC (permalink / raw)
  To: vbabka
  Cc: harry, akpm, hao.li, cl, rientjes, roman.gushchin, linux-mm,
	linux-kernel, zhang.run, cai.qu

Vlastimil Babka (SUSE) wrote:
> On 6/12/26 14:52, hu.shengming@zte.com.cn wrote:
> > Vlastimil Babka (SUSE) wrote:
> >> The two flags are added internally so there's no point for warning if
> >> they are passed by the caller as well, so allow them. This will allow
> >> simplifying obj_ext allocation under kmalloc_nolock().
> >> 
> >> Also it's not necessary to have the extra alloc_gfp variable for adding
> >> the two flags. The original gfp_flags parameter is not used anywhere
> >> except for the warning. So remove alloc_gfp and directly modify and use
> >> gfp_flags everywhere.
> >> 
> >> Signed-off-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
> >> ---
> >>  include/linux/slab.h |  3 ++-
> >>  mm/slub.c            | 19 ++++++++++---------
> >>  2 files changed, 12 insertions(+), 10 deletions(-)
> >> 
> >> diff --git a/include/linux/slab.h b/include/linux/slab.h
> >> index ce1c867dc0ba..b955f3cbb732 100644
> >> --- a/include/linux/slab.h
> >> +++ b/include/linux/slab.h
> >> @@ -1040,7 +1040,8 @@ void *_kmalloc_nolock_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t gfp_flags, in
> >>   * kmalloc_nolock - Allocate an object of given size from any context.
> >>   * @size: size to allocate
> >>   * @gfp_flags: GFP flags. Only __GFP_ACCOUNT, __GFP_ZERO, __GFP_NO_OBJ_EXT
> >> - * allowed.
> >> + * allowed. Also __GFP_NOWARN and __GFP_NOMEMALLOC are allowed but added
> >> + * internally thus not necessary.
> >>   * @node: node number of the target node.
> >>   *
> >>   * Return: pointer to the new object or NULL in case of error.
> >> diff --git a/mm/slub.c b/mm/slub.c
> >> index 6845e15c148a..847cad5203b2 100644
> >> --- a/mm/slub.c
> >> +++ b/mm/slub.c
> >> @@ -5388,7 +5388,6 @@ EXPORT_SYMBOL(__kmalloc_noprof);
> >>  
> >>  void *_kmalloc_nolock_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t gfp_flags, int node)
> >>  {
> >> -    gfp_t alloc_gfp = __GFP_NOWARN | __GFP_NOMEMALLOC | gfp_flags;
> >>      size_t orig_size = size;
> >>      unsigned int alloc_flags = SLAB_ALLOC_TRYLOCK;
> >>      struct kmem_cache *s;
> >> @@ -5396,7 +5395,9 @@ void *_kmalloc_nolock_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t gfp_flags, in
> >>      void *ret;
> >>  
> >>      VM_WARN_ON_ONCE(gfp_flags & ~(__GFP_ACCOUNT | __GFP_ZERO |
> >> -                      __GFP_NO_OBJ_EXT));
> >> +            __GFP_NO_OBJ_EXT | __GFP_NOWARN | __GFP_NOMEMALLOC));
> >> +
> >> +    gfp_flags |= __GFP_NOWARN | __GFP_NOMEMALLOC;
> >>  
> > 
> > Hi Vlastimil,
> > 
> > While reviewing your patch, I spotted a potential GFP flag mismatch along the kmalloc_flags()
> > -> __kmalloc_nolock_noprof() call path. I cloned the slab/for-next branch to verify this and
> > successfully triggered a VM_WARN_ON_ONCE() in the __kmalloc_nolock_noprof() path.
> > 
> > Here is the observed trace:
> > 
> > [   57.283791] ------------[ cut here ]------------
> > [   57.284226] WARNING: mm/slub.c:5407 at __kmalloc_nolock_noprof+0x3ec/0x450, CPU#6: insmod/379
> > [   57.285060] Modules linked in: slub_nolock(O+)
> > [   57.285494] CPU: 6 UID: 0 PID: 379 Comm: insmod Tainted: G           O        7.1.0-rc3-00036-g5ade53586fae-dirty #5 PREEMPT(lazy) 
> > [   57.286608] Tainted: [O]=OOT_MODULE
> > [   57.286941] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.1-0-ga5cab58e9a3f-prebuilt.qemu.org 04/01/2014
> > [   57.288018] RIP: 0010:__kmalloc_nolock_noprof+0x3ec/0x450
> > [   57.288543] Code: 01 00 8b 4c 24 04 41 89 c2 e9 dd fc ff ff b8 10 00 00 00 e9 f9 fd ff ff 90 0f 0b 90 f7 04 24 ff de b7 ff 0f 84 54
> > [   57.290252] RSP: 0018:ffffa82840c73b68 EFLAGS: 00010206
> > [   57.290752] RAX: 0000000000000000 RBX: 0000000000000003 RCX: ffffa82840c73bc8
> > [   57.291428] RDX: 0000000000000000 RSI: 00000000002c2100 RDI: 0000000000000100
> > [   57.292124] RBP: 0000000000000000 R08: ffffffffb853c968 R09: 0000000000009ffb
> > [   57.292821] R10: 00000000000001d7 R11: ffffffffb850c980 R12: 00000000002c2100
> > [   57.293485] R13: 0000000000000000 R14: ffffa82840c73bc8 R15: 0000000000000003
> > [   57.294159] FS:  0000000006fa8880(0000) GS:ffff8f4ef9d5a000(0000) knlGS:0000000000000000
> > [   57.294914] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> > [   57.295464] CR2: 0000000006fac528 CR3: 000000003f9b6003 CR4: 0000000000770ef0
> > [   57.296124] PKRU: 55555554
> > [   57.296443] Call Trace:
> > [   57.296702]  <TASK>
> > [   57.296914]  ? vprintk_emit+0x22e/0x280
> > [   57.297295]  __kmalloc_flags_noprof+0x216/0x530
> > [   57.297735]  ? _printk+0x56/0x70
> > [   57.298053]  ? alloc_slab_obj_exts+0x89/0x1e0
> > [   57.298474]  alloc_slab_obj_exts+0x89/0x1e0
> > [   57.298876]  new_slab+0x2bc/0x660
> > [   57.299200]  ___slab_alloc+0x2ae/0x660
> > [   57.299603]  __kmalloc_nolock_noprof+0x151/0x450
> > [   57.300050]  _kmalloc_nolock_noprof+0x47/0x70
> > [   57.300490]  ? slub_nolock_init+0x127/0xff0 [slub_nolock]
> > [   57.301013]  slub_nolock_init+0x127/0xff0 [slub_nolock]
> > [   57.301566]  ? __pfx_slub_nolock_init+0x10/0x10 [slub_nolock]
> > [   57.302197]  do_one_initcall+0x44/0x220
> > [   57.302598]  ? do_init_module+0x1e/0x240
> > [   57.302990]  do_init_module+0x5f/0x240
> > [   57.303357]  __do_sys_init_module+0x162/0x190
> > [   57.303783]  do_syscall_64+0xf7/0x550
> > [   57.304159]  entry_SYSCALL_64_after_hwframe+0x77/0x7f
> > [   57.304648] RIP: 0033:0x4b8839
> > [   57.304954] Code: 00 f3 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 40
> > [   57.306676] RSP: 002b:00007ffea38fdce8 EFLAGS: 00000246 ORIG_RAX: 00000000000000af
> > [   57.307376] RAX: ffffffffffffffda RBX: 00007ffea38fe080 RCX: 00000000004b8839
> > [   57.308044] RDX: 000000000062d4b5 RSI: 0000000000002790 RDI: 0000000006fa9d20
> > [   57.308710] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000002790
> > [   57.309366] R10: 0000000006fa9cc0 R11: 0000000000000246 R12: 00007ffea38fe088
> > [   57.310040] R13: 000000000062d4b5 R14: 0000000000000000 R15: 0000000000000000
> > [   57.310737]  </TASK>
> > [   57.310963] ---[ end trace 0000000000000000 ]---
> > 
> > With "# CONFIG_KMALLOC_PARTITION_CACHES is not set":
> > RSI: 00000000002c2100 -> gfp_flags
> > 
> > Decoding the GFP bits:
> > 
> >   0x00000100 = __GFP_ZERO
> >   0x00002000 = __GFP_NOWARN
> >   0x00080000 = __GFP_NOMEMALLOC
> >   0x00040000 = __GFP_COMP
> >   0x00200000 = __GFP_THISNODE
> > 
> > The root cause:
> > 
> > Previously, the obj_ext allocation path(alloc_slab_obj_exts()) called kmalloc_nolock() with a
> > fixed set of flags(__GFP_ZERO | __GFP_NO_OBJ_EXT). After switching to kmalloc_flags(), the
> > full GFP mask from the upper allocation path propagates through the call chain.
> > 
> > In detail, ___slab_alloc() may append __GFP_THISNODE, and allocate_slab() adds __GFP_COMP
> > via s->allocflags. Both flags flow down unchanged into __kmalloc_nolock_noprof().
> > 
> > This patch only permits four flags (__GFP_ACCOUNT, __GFP_ZERO, __GFP_NOWARN and __GFP_NOMEMALLOC).
> > Since neither __GFP_THISNODE nor __GFP_COMP is in the allowed set, the warning is triggered.
> > 
> > Would the following fix be acceptable?
> > 
> >     +#define KMALLOC_NOLOCK_ALLOWED_GFP \
> >     +       (__GFP_ACCOUNT | __GFP_ZERO | __GFP_NOWARN | __GFP_NOMEMALLOC)
> >     +
> >     /*
> >     * The only version of kmalloc_node() that takes alloc_flags and thus can
> >     * determine on its own whether to handle the allocation via kmalloc_nolock() or
> >     @@ -5548,6 +5564,7 @@ void *__kmalloc_flags_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t flags,
> >                     return __do_kmalloc_node(size, NULL, flags, node,
> >                                     PASS_TOKEN_PARAM(token), &ac);
> >             } else {
> >     +               flags &= KMALLOC_NOLOCK_ALLOWED_GFP;
> >                     return __kmalloc_nolock_noprof(PASS_TOKEN_PARAMS(size, token),
> >                                                 flags, node, &ac);
> >             }
> 
> Thanks, Hao Li pointed out __GFP_THISNODE and I filtered it from nested
> allocations like this:
> https://lore.kernel.org/all/49f1bf1e-fcaf-48fa-a7b1-f8ee78b19762@kernel.org/
> It makes sense to filter out __GFP_COMP too as that's a page allocator flag
> and not useful for (nested) kmalloc allocations, so I'll add that

Looks like I'm a beat behind on this one — this approach makes perfect sense to me. :-)

--
With Best Regards,
Shengming

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 13/16] mm/slab: allow __GFP_NOMEMALLOC and __GFP_NOWARN for kmalloc_nolock()
  2026-06-12  6:57   ` Hao Li
@ 2026-06-15  5:06     ` Suren Baghdasaryan
  0 siblings, 0 replies; 6+ messages in thread
From: Suren Baghdasaryan @ 2026-06-15  5:06 UTC (permalink / raw)
  To: Hao Li
  Cc: Vlastimil Babka (SUSE),
	Harry Yoo, Christoph Lameter, David Rientjes, Roman Gushchin,
	Alexei Starovoitov, Andrew Morton, Johannes Weiner, Michal Hocko,
	Shakeel Butt, Alexander Potapenko, Marco Elver, Dmitry Vyukov,
	kasan-dev, linux-mm, linux-kernel, cgroups

On Thu, Jun 11, 2026 at 11:57 PM Hao Li <hao.li@linux.dev> wrote:
>
> On Wed, Jun 10, 2026 at 05:40:15PM +0200, Vlastimil Babka (SUSE) wrote:
> > The two flags are added internally so there's no point for warning if
> > they are passed by the caller as well, so allow them. This will allow
> > simplifying obj_ext allocation under kmalloc_nolock().
> >
> > Also it's not necessary to have the extra alloc_gfp variable for adding
> > the two flags. The original gfp_flags parameter is not used anywhere
> > except for the warning. So remove alloc_gfp and directly modify and use
> > gfp_flags everywhere.
> >
> > Signed-off-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
> > ---
>
> LGTM
> Reviewed-by: Hao Li <hao.li@linux.dev>

Reviewed-by: Suren Baghdasaryan <surenb@google.com>

>
> --
> Thanks,
> Hao

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 13/16] mm/slab: allow __GFP_NOMEMALLOC and __GFP_NOWARN for kmalloc_nolock()
  2026-06-10 15:40 ` [PATCH v2 13/16] mm/slab: allow __GFP_NOMEMALLOC and __GFP_NOWARN for kmalloc_nolock() Vlastimil Babka (SUSE)
@ 2026-06-12  6:57   ` Hao Li
  2026-06-15  5:06     ` Suren Baghdasaryan
  0 siblings, 1 reply; 6+ messages in thread
From: Hao Li @ 2026-06-12  6:57 UTC (permalink / raw)
  To: Vlastimil Babka (SUSE)
  Cc: Harry Yoo, Christoph Lameter, David Rientjes, Roman Gushchin,
	Suren Baghdasaryan, Alexei Starovoitov, Andrew Morton,
	Johannes Weiner, Michal Hocko, Shakeel Butt, Alexander Potapenko,
	Marco Elver, Dmitry Vyukov, kasan-dev, linux-mm, linux-kernel,
	cgroups

On Wed, Jun 10, 2026 at 05:40:15PM +0200, Vlastimil Babka (SUSE) wrote:
> The two flags are added internally so there's no point for warning if
> they are passed by the caller as well, so allow them. This will allow
> simplifying obj_ext allocation under kmalloc_nolock().
> 
> Also it's not necessary to have the extra alloc_gfp variable for adding
> the two flags. The original gfp_flags parameter is not used anywhere
> except for the warning. So remove alloc_gfp and directly modify and use
> gfp_flags everywhere.
> 
> Signed-off-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
> ---

LGTM
Reviewed-by: Hao Li <hao.li@linux.dev>

-- 
Thanks,
Hao

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v2 13/16] mm/slab: allow __GFP_NOMEMALLOC and __GFP_NOWARN for kmalloc_nolock()
  2026-06-10 15:40 [PATCH v2 00/16] mm/slab: introduce alloc_flags and slab_alloc_context Vlastimil Babka (SUSE)
@ 2026-06-10 15:40 ` Vlastimil Babka (SUSE)
  2026-06-12  6:57   ` Hao Li
  0 siblings, 1 reply; 6+ messages in thread
From: Vlastimil Babka (SUSE) @ 2026-06-10 15:40 UTC (permalink / raw)
  To: Harry Yoo
  Cc: Hao Li, Christoph Lameter, David Rientjes, Roman Gushchin,
	Suren Baghdasaryan, Alexei Starovoitov, Andrew Morton,
	Johannes Weiner, Michal Hocko, Shakeel Butt, Alexander Potapenko,
	Marco Elver, Dmitry Vyukov, kasan-dev, linux-mm, linux-kernel,
	cgroups, Vlastimil Babka (SUSE)

The two flags are added internally so there's no point for warning if
they are passed by the caller as well, so allow them. This will allow
simplifying obj_ext allocation under kmalloc_nolock().

Also it's not necessary to have the extra alloc_gfp variable for adding
the two flags. The original gfp_flags parameter is not used anywhere
except for the warning. So remove alloc_gfp and directly modify and use
gfp_flags everywhere.

Signed-off-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
---
 include/linux/slab.h |  3 ++-
 mm/slub.c            | 19 ++++++++++---------
 2 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/include/linux/slab.h b/include/linux/slab.h
index ce1c867dc0ba..b955f3cbb732 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -1040,7 +1040,8 @@ void *_kmalloc_nolock_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t gfp_flags, in
  * kmalloc_nolock - Allocate an object of given size from any context.
  * @size: size to allocate
  * @gfp_flags: GFP flags. Only __GFP_ACCOUNT, __GFP_ZERO, __GFP_NO_OBJ_EXT
- * allowed.
+ * allowed. Also __GFP_NOWARN and __GFP_NOMEMALLOC are allowed but added
+ * internally thus not necessary.
  * @node: node number of the target node.
  *
  * Return: pointer to the new object or NULL in case of error.
diff --git a/mm/slub.c b/mm/slub.c
index 6845e15c148a..847cad5203b2 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -5388,7 +5388,6 @@ EXPORT_SYMBOL(__kmalloc_noprof);
 
 void *_kmalloc_nolock_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t gfp_flags, int node)
 {
-	gfp_t alloc_gfp = __GFP_NOWARN | __GFP_NOMEMALLOC | gfp_flags;
 	size_t orig_size = size;
 	unsigned int alloc_flags = SLAB_ALLOC_TRYLOCK;
 	struct kmem_cache *s;
@@ -5396,7 +5395,9 @@ void *_kmalloc_nolock_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t gfp_flags, in
 	void *ret;
 
 	VM_WARN_ON_ONCE(gfp_flags & ~(__GFP_ACCOUNT | __GFP_ZERO |
-				      __GFP_NO_OBJ_EXT));
+			__GFP_NO_OBJ_EXT | __GFP_NOWARN | __GFP_NOMEMALLOC));
+
+	gfp_flags |= __GFP_NOWARN | __GFP_NOMEMALLOC;
 
 	if (unlikely(!size))
 		return ZERO_SIZE_PTR;
@@ -5415,7 +5416,7 @@ void *_kmalloc_nolock_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t gfp_flags, in
 retry:
 	if (unlikely(size > KMALLOC_MAX_CACHE_SIZE))
 		return NULL;
-	s = kmalloc_slab(size, NULL, alloc_gfp, PASS_TOKEN_PARAM(token));
+	s = kmalloc_slab(size, NULL, gfp_flags, PASS_TOKEN_PARAM(token));
 
 	if (!(s->flags & __CMPXCHG_DOUBLE) && !kmem_cache_debug(s))
 		/*
@@ -5429,7 +5430,7 @@ void *_kmalloc_nolock_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t gfp_flags, in
 		 */
 		return NULL;
 
-	ret = alloc_from_pcs(s, alloc_gfp, alloc_flags, node);
+	ret = alloc_from_pcs(s, gfp_flags, alloc_flags, node);
 	if (ret)
 		goto success;
 
@@ -5445,7 +5446,7 @@ void *_kmalloc_nolock_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t gfp_flags, in
 	 * kfence_alloc. Hence call __slab_alloc_node() (at most twice)
 	 * and slab_post_alloc_hook() directly.
 	 */
-	ret = __slab_alloc_node(s, alloc_gfp, node, &ac);
+	ret = __slab_alloc_node(s, gfp_flags, node, &ac);
 
 	/*
 	 * It's possible we failed due to trylock as we preempted someone with
@@ -5458,8 +5459,8 @@ void *_kmalloc_nolock_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t gfp_flags, in
 		size = s->object_size + 1;
 		/*
 		 * Another alternative is to
-		 * if (memcg) alloc_gfp &= ~__GFP_ACCOUNT;
-		 * else if (!memcg) alloc_gfp |= __GFP_ACCOUNT;
+		 * if (memcg) gfp_flags &= ~__GFP_ACCOUNT;
+		 * else if (!memcg) gfp_flags |= __GFP_ACCOUNT;
 		 * to retry from bucket of the same size.
 		 */
 		can_retry = false;
@@ -5468,9 +5469,9 @@ void *_kmalloc_nolock_noprof(DECL_TOKEN_PARAMS(size, token), gfp_t gfp_flags, in
 
 success:
 	maybe_wipe_obj_freeptr(s, ret);
-	slab_post_alloc_hook(s, alloc_gfp, 1, &ret, &ac);
+	slab_post_alloc_hook(s, gfp_flags, 1, &ret, &ac);
 
-	ret = kasan_kmalloc(s, ret, orig_size, alloc_gfp);
+	ret = kasan_kmalloc(s, ret, orig_size, gfp_flags);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(_kmalloc_nolock_noprof);

-- 
2.54.0


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-06-15  5:06 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-12 12:52 [PATCH v2 13/16] mm/slab: allow __GFP_NOMEMALLOC and __GFP_NOWARN for kmalloc_nolock() hu.shengming
2026-06-12 13:00 ` Vlastimil Babka (SUSE)
2026-06-12 13:14   ` hu.shengming
  -- strict thread matches above, loose matches on Subject: below --
2026-06-10 15:40 [PATCH v2 00/16] mm/slab: introduce alloc_flags and slab_alloc_context Vlastimil Babka (SUSE)
2026-06-10 15:40 ` [PATCH v2 13/16] mm/slab: allow __GFP_NOMEMALLOC and __GFP_NOWARN for kmalloc_nolock() Vlastimil Babka (SUSE)
2026-06-12  6:57   ` Hao Li
2026-06-15  5:06     ` Suren Baghdasaryan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®