Commit f4957d5b authored by Alexey Dobriyan's avatar Alexey Dobriyan Committed by Linus Torvalds

slab: make kmem_cache_create() work with 32-bit sizes

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/20180305200730.15812-6-adobriyan@gmail.comSigned-off-by: default avatarAlexey Dobriyan <adobriyan@gmail.com>
Cc: Christoph Lameter <cl@linux.com>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: David Rientjes <rientjes@google.com>
Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 361d575e
...@@ -137,11 +137,12 @@ bool slab_is_available(void); ...@@ -137,11 +137,12 @@ bool slab_is_available(void);
extern bool usercopy_fallback; extern bool usercopy_fallback;
struct kmem_cache *kmem_cache_create(const char *name, size_t size, struct kmem_cache *kmem_cache_create(const char *name, unsigned int size,
size_t align, slab_flags_t flags, unsigned int align, slab_flags_t flags,
void (*ctor)(void *)); void (*ctor)(void *));
struct kmem_cache *kmem_cache_create_usercopy(const char *name, 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, size_t useroffset, size_t usersize,
void (*ctor)(void *)); void (*ctor)(void *));
void kmem_cache_destroy(struct kmem_cache *); void kmem_cache_destroy(struct kmem_cache *);
......
...@@ -1877,7 +1877,7 @@ slab_flags_t kmem_cache_flags(unsigned long object_size, ...@@ -1877,7 +1877,7 @@ slab_flags_t kmem_cache_flags(unsigned long object_size,
} }
struct kmem_cache * 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 flags, void (*ctor)(void *))
{ {
struct kmem_cache *cachep; struct kmem_cache *cachep;
......
...@@ -101,11 +101,11 @@ extern void create_boot_cache(struct kmem_cache *, const char *name, ...@@ -101,11 +101,11 @@ extern void create_boot_cache(struct kmem_cache *, const char *name,
unsigned int useroffset, unsigned int usersize); unsigned int useroffset, unsigned int usersize);
int slab_unmergeable(struct kmem_cache *s); 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 *)); slab_flags_t flags, const char *name, void (*ctor)(void *));
#ifndef CONFIG_SLOB #ifndef CONFIG_SLOB
struct kmem_cache * 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 flags, void (*ctor)(void *));
slab_flags_t kmem_cache_flags(unsigned long object_size, slab_flags_t kmem_cache_flags(unsigned long object_size,
...@@ -113,7 +113,7 @@ slab_flags_t kmem_cache_flags(unsigned long object_size, ...@@ -113,7 +113,7 @@ slab_flags_t kmem_cache_flags(unsigned long object_size,
void (*ctor)(void *)); void (*ctor)(void *));
#else #else
static inline struct kmem_cache * 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 *)) slab_flags_t flags, void (*ctor)(void *))
{ return NULL; } { return NULL; }
......
...@@ -82,7 +82,7 @@ unsigned int kmem_cache_size(struct kmem_cache *s) ...@@ -82,7 +82,7 @@ unsigned int kmem_cache_size(struct kmem_cache *s)
EXPORT_SYMBOL(kmem_cache_size); EXPORT_SYMBOL(kmem_cache_size);
#ifdef CONFIG_DEBUG_VM #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; struct kmem_cache *s = NULL;
...@@ -113,7 +113,7 @@ static int kmem_cache_sanity_check(const char *name, size_t size) ...@@ -113,7 +113,7 @@ static int kmem_cache_sanity_check(const char *name, size_t size)
return 0; return 0;
} }
#else #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; return 0;
} }
...@@ -280,8 +280,8 @@ static inline void memcg_unlink_cache(struct kmem_cache *s) ...@@ -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 * 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. * flags, a user specified alignment and the size of the objects.
*/ */
static unsigned long calculate_alignment(slab_flags_t flags, static unsigned int calculate_alignment(slab_flags_t flags,
unsigned long align, unsigned long size) unsigned int align, unsigned int size)
{ {
/* /*
* If the user wants hardware cache aligned objects then follow that * If the user wants hardware cache aligned objects then follow that
...@@ -291,7 +291,7 @@ static unsigned long calculate_alignment(slab_flags_t flags, ...@@ -291,7 +291,7 @@ static unsigned long calculate_alignment(slab_flags_t flags,
* alignment though. If that is greater then use it. * alignment though. If that is greater then use it.
*/ */
if (flags & SLAB_HWCACHE_ALIGN) { if (flags & SLAB_HWCACHE_ALIGN) {
unsigned long ralign; unsigned int ralign;
ralign = cache_line_size(); ralign = cache_line_size();
while (size <= ralign / 2) while (size <= ralign / 2)
...@@ -331,7 +331,7 @@ int slab_unmergeable(struct kmem_cache *s) ...@@ -331,7 +331,7 @@ int slab_unmergeable(struct kmem_cache *s)
return 0; 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 *)) slab_flags_t flags, const char *name, void (*ctor)(void *))
{ {
struct kmem_cache *s; struct kmem_cache *s;
...@@ -379,7 +379,7 @@ struct kmem_cache *find_mergeable(size_t size, size_t align, ...@@ -379,7 +379,7 @@ struct kmem_cache *find_mergeable(size_t size, size_t align,
} }
static struct kmem_cache *create_cache(const char *name, 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, slab_flags_t flags, size_t useroffset,
size_t usersize, void (*ctor)(void *), size_t usersize, void (*ctor)(void *),
struct mem_cgroup *memcg, struct kmem_cache *root_cache) struct mem_cgroup *memcg, struct kmem_cache *root_cache)
...@@ -452,7 +452,8 @@ static struct kmem_cache *create_cache(const char *name, ...@@ -452,7 +452,8 @@ static struct kmem_cache *create_cache(const char *name,
* as davem. * as davem.
*/ */
struct kmem_cache * 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, slab_flags_t flags, size_t useroffset, size_t usersize,
void (*ctor)(void *)) void (*ctor)(void *))
{ {
...@@ -532,7 +533,7 @@ kmem_cache_create_usercopy(const char *name, size_t size, size_t align, ...@@ -532,7 +533,7 @@ kmem_cache_create_usercopy(const char *name, size_t size, size_t align,
EXPORT_SYMBOL(kmem_cache_create_usercopy); EXPORT_SYMBOL(kmem_cache_create_usercopy);
struct kmem_cache * 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 *)) slab_flags_t flags, void (*ctor)(void *))
{ {
return kmem_cache_create_usercopy(name, size, align, flags, 0, 0, return kmem_cache_create_usercopy(name, size, align, flags, 0, 0,
......
...@@ -4242,7 +4242,7 @@ void __init kmem_cache_init_late(void) ...@@ -4242,7 +4242,7 @@ void __init kmem_cache_init_late(void)
} }
struct kmem_cache * 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 flags, void (*ctor)(void *))
{ {
struct kmem_cache *s, *c; struct kmem_cache *s, *c;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment