Skip to content

Commit f1dce1f

Browse files
committed
Merge tag 'slab-for-6.12-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/vbabka/slab
Pull slab fix from Vlastimil Babka: - Fix for duplicate caches in some arm64 configurations with CONFIG_SLAB_BUCKETS (Koichiro Den) * tag 'slab-for-6.12-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/vbabka/slab: mm/slab: fix warning caused by duplicate kmem_cache creation in kmem_buckets_create
2 parents 9183e03 + 9c9201a commit f1dce1f

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)