Skip to content

Commit 9c9201a

Browse files
lkpdntehcaster
authored andcommitted
mm/slab: fix warning caused by duplicate kmem_cache creation in kmem_buckets_create
Commit b035f5a ("mm: slab: reduce the kmalloc() minimum alignment if DMA bouncing possible") reduced ARCH_KMALLOC_MINALIGN to 8 on arm64. However, with KASAN_HW_TAGS enabled, arch_slab_minalign() becomes 16. This causes kmalloc_caches[*][8] to be aliased to kmalloc_caches[*][16], resulting in kmem_buckets_create() attempting to create a kmem_cache for size 16 twice. This duplication triggers warnings on boot: [ 2.325108] ------------[ cut here ]------------ [ 2.325135] kmem_cache of name 'memdup_user-16' already exists [ 2.325783] WARNING: CPU: 0 PID: 1 at mm/slab_common.c:107 __kmem_cache_create_args+0xb8/0x3b0 [ 2.327957] Modules linked in: [ 2.328550] CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.12.0-rc5mm-unstable-arm64+ #12 [ 2.328683] Hardware name: QEMU QEMU Virtual Machine, BIOS 2024.02-2 03/11/2024 [ 2.328790] pstate: 61000009 (nZCv daif -PAN -UAO -TCO +DIT -SSBS BTYPE=--) [ 2.328911] pc : __kmem_cache_create_args+0xb8/0x3b0 [ 2.328930] lr : __kmem_cache_create_args+0xb8/0x3b0 [ 2.328942] sp : ffff800083d6fc50 [ 2.328961] x29: ffff800083d6fc50 x28: f2ff0000c1674410 x27: ffff8000820b0598 [ 2.329061] x26: 000000007fffffff x25: 0000000000000010 x24: 0000000000002000 [ 2.329101] x23: ffff800083d6fce8 x22: ffff8000832222e8 x21: ffff800083222388 [ 2.329118] x20: f2ff0000c1674410 x19: f5ff0000c16364c0 x18: ffff800083d80030 [ 2.329135] x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000 [ 2.329152] x14: 0000000000000000 x13: 0a73747369786520 x12: 79646165726c6120 [ 2.329169] x11: 656820747563205b x10: 2d2d2d2d2d2d2d2d x9 : 0000000000000000 [ 2.329194] x8 : 0000000000000000 x7 : 0000000000000000 x6 : 0000000000000000 [ 2.329210] x5 : 0000000000000000 x4 : 0000000000000000 x3 : 0000000000000000 [ 2.329226] x2 : 0000000000000000 x1 : 0000000000000000 x0 : 0000000000000000 [ 2.329291] Call trace: [ 2.329407] __kmem_cache_create_args+0xb8/0x3b0 [ 2.329499] kmem_buckets_create+0xfc/0x320 [ 2.329526] init_user_buckets+0x34/0x78 [ 2.329540] do_one_initcall+0x64/0x3c8 [ 2.329550] kernel_init_freeable+0x26c/0x578 [ 2.329562] kernel_init+0x3c/0x258 [ 2.329574] ret_from_fork+0x10/0x20 [ 2.329698] ---[ end trace 0000000000000000 ]--- [ 2.403704] ------------[ cut here ]------------ [ 2.404716] kmem_cache of name 'msg_msg-16' already exists [ 2.404801] WARNING: CPU: 2 PID: 1 at mm/slab_common.c:107 __kmem_cache_create_args+0xb8/0x3b0 [ 2.404842] Modules linked in: [ 2.404971] CPU: 2 UID: 0 PID: 1 Comm: swapper/0 Tainted: G W 6.12.0-rc5mm-unstable-arm64+ #12 [ 2.405026] Tainted: [W]=WARN [ 2.405043] Hardware name: QEMU QEMU Virtual Machine, BIOS 2024.02-2 03/11/2024 [ 2.405057] pstate: 60400009 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 2.405079] pc : __kmem_cache_create_args+0xb8/0x3b0 [ 2.405100] lr : __kmem_cache_create_args+0xb8/0x3b0 [ 2.405111] sp : ffff800083d6fc50 [ 2.405115] x29: ffff800083d6fc50 x28: fbff0000c1674410 x27: ffff8000820b0598 [ 2.405135] x26: 000000000000ffd0 x25: 0000000000000010 x24: 0000000000006000 [ 2.405153] x23: ffff800083d6fce8 x22: ffff8000832222e8 x21: ffff800083222388 [ 2.405169] x20: fbff0000c1674410 x19: fdff0000c163d6c0 x18: ffff800083d80030 [ 2.405185] x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000 [ 2.405201] x14: 0000000000000000 x13: 0a73747369786520 x12: 79646165726c6120 [ 2.405217] x11: 656820747563205b x10: 2d2d2d2d2d2d2d2d x9 : 0000000000000000 [ 2.405233] x8 : 0000000000000000 x7 : 0000000000000000 x6 : 0000000000000000 [ 2.405248] x5 : 0000000000000000 x4 : 0000000000000000 x3 : 0000000000000000 [ 2.405271] x2 : 0000000000000000 x1 : 0000000000000000 x0 : 0000000000000000 [ 2.405287] Call trace: [ 2.405293] __kmem_cache_create_args+0xb8/0x3b0 [ 2.405305] kmem_buckets_create+0xfc/0x320 [ 2.405315] init_msg_buckets+0x34/0x78 [ 2.405326] do_one_initcall+0x64/0x3c8 [ 2.405337] kernel_init_freeable+0x26c/0x578 [ 2.405348] kernel_init+0x3c/0x258 [ 2.405360] ret_from_fork+0x10/0x20 [ 2.405370] ---[ end trace 0000000000000000 ]--- To address this, alias kmem_cache for sizes smaller than min alignment to the aligned sized kmem_cache, as done with the default system kmalloc bucket. Fixes: b32801d ("mm/slab: Introduce kmem_buckets_create() and family") Cc: <[email protected]> # v6.11+ Signed-off-by: Koichiro Den <[email protected]> Reviewed-by: Catalin Marinas <[email protected]> Tested-by: Catalin Marinas <[email protected]> Signed-off-by: Vlastimil Babka <[email protected]>
1 parent 7045738 commit 9c9201a

File tree

1 file changed

+20
-11
lines changed

1 file changed

+20
-11
lines changed

mm/slab_common.c

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -380,8 +380,11 @@ kmem_buckets *kmem_buckets_create(const char *name, slab_flags_t flags,
380380
unsigned int usersize,
381381
void (*ctor)(void *))
382382
{
383+
unsigned long mask = 0;
384+
unsigned int idx;
383385
kmem_buckets *b;
384-
int idx;
386+
387+
BUILD_BUG_ON(ARRAY_SIZE(kmalloc_caches[KMALLOC_NORMAL]) > BITS_PER_LONG);
385388

386389
/*
387390
* When the separate buckets API is not built in, just return
@@ -403,7 +406,7 @@ kmem_buckets *kmem_buckets_create(const char *name, slab_flags_t flags,
403406
for (idx = 0; idx < ARRAY_SIZE(kmalloc_caches[KMALLOC_NORMAL]); idx++) {
404407
char *short_size, *cache_name;
405408
unsigned int cache_useroffset, cache_usersize;
406-
unsigned int size;
409+
unsigned int size, aligned_idx;
407410

408411
if (!kmalloc_caches[KMALLOC_NORMAL][idx])
409412
continue;
@@ -416,29 +419,35 @@ kmem_buckets *kmem_buckets_create(const char *name, slab_flags_t flags,
416419
if (WARN_ON(!short_size))
417420
goto fail;
418421

419-
cache_name = kasprintf(GFP_KERNEL, "%s-%s", name, short_size + 1);
420-
if (WARN_ON(!cache_name))
421-
goto fail;
422-
423422
if (useroffset >= size) {
424423
cache_useroffset = 0;
425424
cache_usersize = 0;
426425
} else {
427426
cache_useroffset = useroffset;
428427
cache_usersize = min(size - cache_useroffset, usersize);
429428
}
430-
(*b)[idx] = kmem_cache_create_usercopy(cache_name, size,
429+
430+
aligned_idx = __kmalloc_index(size, false);
431+
if (!(*b)[aligned_idx]) {
432+
cache_name = kasprintf(GFP_KERNEL, "%s-%s", name, short_size + 1);
433+
if (WARN_ON(!cache_name))
434+
goto fail;
435+
(*b)[aligned_idx] = kmem_cache_create_usercopy(cache_name, size,
431436
0, flags, cache_useroffset,
432437
cache_usersize, ctor);
433-
kfree(cache_name);
434-
if (WARN_ON(!(*b)[idx]))
435-
goto fail;
438+
kfree(cache_name);
439+
if (WARN_ON(!(*b)[aligned_idx]))
440+
goto fail;
441+
set_bit(aligned_idx, &mask);
442+
}
443+
if (idx != aligned_idx)
444+
(*b)[idx] = (*b)[aligned_idx];
436445
}
437446

438447
return b;
439448

440449
fail:
441-
for (idx = 0; idx < ARRAY_SIZE(kmalloc_caches[KMALLOC_NORMAL]); idx++)
450+
for_each_set_bit(idx, &mask, ARRAY_SIZE(kmalloc_caches[KMALLOC_NORMAL]))
442451
kmem_cache_destroy((*b)[idx]);
443452
kmem_cache_free(kmem_buckets_cache, b);
444453

0 commit comments

Comments
 (0)