Skip to content

Commit

Permalink
slab: make kmem_cache_create() work with 32-bit sizes
Browse files Browse the repository at this point in the history
struct kmem_cache::size and ::align were always 32-bit.

Out of curiosity I created 4GB kmem_cache, it oopsed with division by 0.
kmem_cache_create(1UL<<32+1) created 1-byte cache as expected.

size_t doesn't work and never did.

Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Alexey Dobriyan <[email protected]>
Cc: Christoph Lameter <[email protected]>
Cc: Pekka Enberg <[email protected]>
Cc: David Rientjes <[email protected]>
Cc: Joonsoo Kim <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Alexey Dobriyan authored and torvalds committed Apr 6, 2018
1 parent 361d575 commit f4957d5
Show file tree
Hide file tree
Showing 5 changed files with 19 additions and 17 deletions.
7 changes: 4 additions & 3 deletions include/linux/slab.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,12 @@ bool slab_is_available(void);

extern bool usercopy_fallback;

struct kmem_cache *kmem_cache_create(const char *name, size_t size,
size_t align, slab_flags_t flags,
struct kmem_cache *kmem_cache_create(const char *name, unsigned int size,
unsigned int align, slab_flags_t flags,
void (*ctor)(void *));
struct kmem_cache *kmem_cache_create_usercopy(const char *name,
size_t size, size_t align, slab_flags_t flags,
unsigned int size, unsigned int align,
slab_flags_t flags,
size_t useroffset, size_t usersize,
void (*ctor)(void *));
void kmem_cache_destroy(struct kmem_cache *);
Expand Down
2 changes: 1 addition & 1 deletion mm/slab.c
Original file line number Diff line number Diff line change
Expand Up @@ -1877,7 +1877,7 @@ slab_flags_t kmem_cache_flags(unsigned long object_size,
}

struct kmem_cache *
__kmem_cache_alias(const char *name, size_t size, size_t align,
__kmem_cache_alias(const char *name, unsigned int size, unsigned int align,
slab_flags_t flags, void (*ctor)(void *))
{
struct kmem_cache *cachep;
Expand Down
6 changes: 3 additions & 3 deletions mm/slab.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,19 +101,19 @@ extern void create_boot_cache(struct kmem_cache *, const char *name,
unsigned int useroffset, unsigned int usersize);

int slab_unmergeable(struct kmem_cache *s);
struct kmem_cache *find_mergeable(size_t size, size_t align,
struct kmem_cache *find_mergeable(unsigned size, unsigned align,
slab_flags_t flags, const char *name, void (*ctor)(void *));
#ifndef CONFIG_SLOB
struct kmem_cache *
__kmem_cache_alias(const char *name, size_t size, size_t align,
__kmem_cache_alias(const char *name, unsigned int size, unsigned int align,
slab_flags_t flags, void (*ctor)(void *));

slab_flags_t kmem_cache_flags(unsigned long object_size,
slab_flags_t flags, const char *name,
void (*ctor)(void *));
#else
static inline struct kmem_cache *
__kmem_cache_alias(const char *name, size_t size, size_t align,
__kmem_cache_alias(const char *name, unsigned int size, unsigned int align,
slab_flags_t flags, void (*ctor)(void *))
{ return NULL; }

Expand Down
19 changes: 10 additions & 9 deletions mm/slab_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ unsigned int kmem_cache_size(struct kmem_cache *s)
EXPORT_SYMBOL(kmem_cache_size);

#ifdef CONFIG_DEBUG_VM
static int kmem_cache_sanity_check(const char *name, size_t size)
static int kmem_cache_sanity_check(const char *name, unsigned int size)
{
struct kmem_cache *s = NULL;

Expand Down Expand Up @@ -113,7 +113,7 @@ static int kmem_cache_sanity_check(const char *name, size_t size)
return 0;
}
#else
static inline int kmem_cache_sanity_check(const char *name, size_t size)
static inline int kmem_cache_sanity_check(const char *name, unsigned int size)
{
return 0;
}
Expand Down Expand Up @@ -280,8 +280,8 @@ static inline void memcg_unlink_cache(struct kmem_cache *s)
* Figure out what the alignment of the objects will be given a set of
* flags, a user specified alignment and the size of the objects.
*/
static unsigned long calculate_alignment(slab_flags_t flags,
unsigned long align, unsigned long size)
static unsigned int calculate_alignment(slab_flags_t flags,
unsigned int align, unsigned int size)
{
/*
* If the user wants hardware cache aligned objects then follow that
Expand All @@ -291,7 +291,7 @@ static unsigned long calculate_alignment(slab_flags_t flags,
* alignment though. If that is greater then use it.
*/
if (flags & SLAB_HWCACHE_ALIGN) {
unsigned long ralign;
unsigned int ralign;

ralign = cache_line_size();
while (size <= ralign / 2)
Expand Down Expand Up @@ -331,7 +331,7 @@ int slab_unmergeable(struct kmem_cache *s)
return 0;
}

struct kmem_cache *find_mergeable(size_t size, size_t align,
struct kmem_cache *find_mergeable(unsigned int size, unsigned int align,
slab_flags_t flags, const char *name, void (*ctor)(void *))
{
struct kmem_cache *s;
Expand Down Expand Up @@ -379,7 +379,7 @@ struct kmem_cache *find_mergeable(size_t size, size_t align,
}

static struct kmem_cache *create_cache(const char *name,
size_t object_size, size_t size, size_t align,
unsigned int object_size, unsigned int size, unsigned int align,
slab_flags_t flags, size_t useroffset,
size_t usersize, void (*ctor)(void *),
struct mem_cgroup *memcg, struct kmem_cache *root_cache)
Expand Down Expand Up @@ -452,7 +452,8 @@ static struct kmem_cache *create_cache(const char *name,
* as davem.
*/
struct kmem_cache *
kmem_cache_create_usercopy(const char *name, size_t size, size_t align,
kmem_cache_create_usercopy(const char *name,
unsigned int size, unsigned int align,
slab_flags_t flags, size_t useroffset, size_t usersize,
void (*ctor)(void *))
{
Expand Down Expand Up @@ -532,7 +533,7 @@ kmem_cache_create_usercopy(const char *name, size_t size, size_t align,
EXPORT_SYMBOL(kmem_cache_create_usercopy);

struct kmem_cache *
kmem_cache_create(const char *name, size_t size, size_t align,
kmem_cache_create(const char *name, unsigned int size, unsigned int align,
slab_flags_t flags, void (*ctor)(void *))
{
return kmem_cache_create_usercopy(name, size, align, flags, 0, 0,
Expand Down
2 changes: 1 addition & 1 deletion mm/slub.c
Original file line number Diff line number Diff line change
Expand Up @@ -4242,7 +4242,7 @@ void __init kmem_cache_init_late(void)
}

struct kmem_cache *
__kmem_cache_alias(const char *name, size_t size, size_t align,
__kmem_cache_alias(const char *name, unsigned int size, unsigned int align,
slab_flags_t flags, void (*ctor)(void *))
{
struct kmem_cache *s, *c;
Expand Down

0 comments on commit f4957d5

Please sign in to comment.