Skip to content

Commit

Permalink
SLUB: fix ARCH_KMALLOC_MINALIGN cases 64 and 256
Browse files Browse the repository at this point in the history
If the minalign is 64 bytes, then the 96 byte cache should not be created
because it would conflict with the 128 byte cache.

If the minalign is 256 bytes, patching the size_index table should not
result in a buffer overrun.

The calculation "(i - 1) / 8" used to access size_index[] is moved to
a separate function as suggested by Christoph Lameter.

Acked-by: Christoph Lameter <cl@linux-foundation.org>
Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com>
Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi>
  • Loading branch information
aakoskin authored and Pekka Enberg committed Aug 30, 2009
1 parent cf5d113 commit acdfcd0
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 10 deletions.
6 changes: 2 additions & 4 deletions include/linux/slub_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,12 +152,10 @@ static __always_inline int kmalloc_index(size_t size)
if (size <= KMALLOC_MIN_SIZE)
return KMALLOC_SHIFT_LOW;

#if KMALLOC_MIN_SIZE <= 64
if (size > 64 && size <= 96)
if (KMALLOC_MIN_SIZE <= 32 && size > 64 && size <= 96)
return 1;
if (size > 128 && size <= 192)
if (KMALLOC_MIN_SIZE <= 64 && size > 128 && size <= 192)
return 2;
#endif
if (size <= 8) return 3;
if (size <= 16) return 4;
if (size <= 32) return 5;
Expand Down
30 changes: 24 additions & 6 deletions mm/slub.c
Original file line number Diff line number Diff line change
Expand Up @@ -2825,6 +2825,11 @@ static s8 size_index[24] = {
2 /* 192 */
};

static inline int size_index_elem(size_t bytes)
{
return (bytes - 1) / 8;
}

static struct kmem_cache *get_slab(size_t size, gfp_t flags)
{
int index;
Expand All @@ -2833,7 +2838,7 @@ static struct kmem_cache *get_slab(size_t size, gfp_t flags)
if (!size)
return ZERO_SIZE_PTR;

index = size_index[(size - 1) / 8];
index = size_index[size_index_elem(size)];
} else
index = fls(size - 1);

Expand Down Expand Up @@ -3188,10 +3193,12 @@ void __init kmem_cache_init(void)
slab_state = PARTIAL;

/* Caches that are not of the two-to-the-power-of size */
if (KMALLOC_MIN_SIZE <= 64) {
if (KMALLOC_MIN_SIZE <= 32) {
create_kmalloc_cache(&kmalloc_caches[1],
"kmalloc-96", 96, GFP_NOWAIT);
caches++;
}
if (KMALLOC_MIN_SIZE <= 64) {
create_kmalloc_cache(&kmalloc_caches[2],
"kmalloc-192", 192, GFP_NOWAIT);
caches++;
Expand All @@ -3218,17 +3225,28 @@ void __init kmem_cache_init(void)
BUILD_BUG_ON(KMALLOC_MIN_SIZE > 256 ||
(KMALLOC_MIN_SIZE & (KMALLOC_MIN_SIZE - 1)));

for (i = 8; i < KMALLOC_MIN_SIZE; i += 8)
size_index[(i - 1) / 8] = KMALLOC_SHIFT_LOW;
for (i = 8; i < KMALLOC_MIN_SIZE; i += 8) {
int elem = size_index_elem(i);
if (elem >= ARRAY_SIZE(size_index))
break;
size_index[elem] = KMALLOC_SHIFT_LOW;
}

if (KMALLOC_MIN_SIZE == 128) {
if (KMALLOC_MIN_SIZE == 64) {
/*
* The 96 byte size cache is not used if the alignment
* is 64 byte.
*/
for (i = 64 + 8; i <= 96; i += 8)
size_index[size_index_elem(i)] = 7;
} else if (KMALLOC_MIN_SIZE == 128) {
/*
* The 192 byte sized cache is not used if the alignment
* is 128 byte. Redirect kmalloc to use the 256 byte cache
* instead.
*/
for (i = 128 + 8; i <= 192; i += 8)
size_index[(i - 1) / 8] = 8;
size_index[size_index_elem(i)] = 8;
}

slab_state = UP;
Expand Down

0 comments on commit acdfcd0

Please sign in to comment.