Skip to content

Commit

Permalink
slub: make struct kmem_cache_order_objects::x unsigned int
Browse files Browse the repository at this point in the history
struct kmem_cache_order_objects is for mixing order and number of
objects, and orders aren't big enough to warrant 64-bit width.

Propagate unsignedness down so that everything fits.

!!! Patch assumes that "PAGE_SIZE << order" doesn't overflow. !!!

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 284b50d commit 19af27a
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 36 deletions.
2 changes: 1 addition & 1 deletion include/linux/slub_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ struct kmem_cache_cpu {
* given order would contain.
*/
struct kmem_cache_order_objects {
unsigned long x;
unsigned int x;
};

/*
Expand Down
74 changes: 39 additions & 35 deletions mm/slub.c
Original file line number Diff line number Diff line change
Expand Up @@ -316,13 +316,13 @@ static inline unsigned int slab_index(void *p, struct kmem_cache *s, void *addr)
return (p - addr) / s->size;
}

static inline int order_objects(int order, unsigned long size, int reserved)
static inline unsigned int order_objects(unsigned int order, unsigned int size, unsigned int reserved)
{
return ((PAGE_SIZE << order) - reserved) / size;
return (((unsigned int)PAGE_SIZE << order) - reserved) / size;
}

static inline struct kmem_cache_order_objects oo_make(int order,
unsigned long size, int reserved)
static inline struct kmem_cache_order_objects oo_make(unsigned int order,
unsigned int size, unsigned int reserved)
{
struct kmem_cache_order_objects x = {
(order << OO_SHIFT) + order_objects(order, size, reserved)
Expand All @@ -331,12 +331,12 @@ static inline struct kmem_cache_order_objects oo_make(int order,
return x;
}

static inline int oo_order(struct kmem_cache_order_objects x)
static inline unsigned int oo_order(struct kmem_cache_order_objects x)
{
return x.x >> OO_SHIFT;
}

static inline int oo_objects(struct kmem_cache_order_objects x)
static inline unsigned int oo_objects(struct kmem_cache_order_objects x)
{
return x.x & OO_MASK;
}
Expand Down Expand Up @@ -1436,7 +1436,7 @@ static inline struct page *alloc_slab_page(struct kmem_cache *s,
gfp_t flags, int node, struct kmem_cache_order_objects oo)
{
struct page *page;
int order = oo_order(oo);
unsigned int order = oo_order(oo);

if (node == NUMA_NO_NODE)
page = alloc_pages(flags, order);
Expand All @@ -1455,8 +1455,8 @@ static inline struct page *alloc_slab_page(struct kmem_cache *s,
/* Pre-initialize the random sequence cache */
static int init_cache_random_seq(struct kmem_cache *s)
{
unsigned int count = oo_objects(s->oo);
int err;
unsigned long i, count = oo_objects(s->oo);

/* Bailout if already initialised */
if (s->random_seq)
Expand All @@ -1471,6 +1471,8 @@ static int init_cache_random_seq(struct kmem_cache *s)

/* Transform to an offset on the set of pages */
if (s->random_seq) {
unsigned int i;

for (i = 0; i < count; i++)
s->random_seq[i] *= s->size;
}
Expand Down Expand Up @@ -2399,7 +2401,7 @@ slab_out_of_memory(struct kmem_cache *s, gfp_t gfpflags, int nid)

pr_warn("SLUB: Unable to allocate memory on node %d, gfp=%#x(%pGg)\n",
nid, gfpflags, &gfpflags);
pr_warn(" cache: %s, object size: %u, buffer size: %u, default order: %d, min order: %d\n",
pr_warn(" cache: %s, object size: %u, buffer size: %u, default order: %u, min order: %u\n",
s->name, s->object_size, s->size, oo_order(s->oo),
oo_order(s->min));

Expand Down Expand Up @@ -3182,9 +3184,9 @@ EXPORT_SYMBOL(kmem_cache_alloc_bulk);
* and increases the number of allocations possible without having to
* take the list_lock.
*/
static int slub_min_order;
static int slub_max_order = PAGE_ALLOC_COSTLY_ORDER;
static int slub_min_objects;
static unsigned int slub_min_order;
static unsigned int slub_max_order = PAGE_ALLOC_COSTLY_ORDER;
static unsigned int slub_min_objects;

/*
* Calculate the order of allocation given an slab object size.
Expand All @@ -3211,20 +3213,21 @@ static int slub_min_objects;
* requested a higher mininum order then we start with that one instead of
* the smallest order which will fit the object.
*/
static inline int slab_order(int size, int min_objects,
int max_order, int fract_leftover, int reserved)
static inline unsigned int slab_order(unsigned int size,
unsigned int min_objects, unsigned int max_order,
unsigned int fract_leftover, unsigned int reserved)
{
int order;
int rem;
int min_order = slub_min_order;
unsigned int min_order = slub_min_order;
unsigned int order;

if (order_objects(min_order, size, reserved) > MAX_OBJS_PER_PAGE)
return get_order(size * MAX_OBJS_PER_PAGE) - 1;

for (order = max(min_order, get_order(min_objects * size + reserved));
for (order = max(min_order, (unsigned int)get_order(min_objects * size + reserved));
order <= max_order; order++) {

unsigned long slab_size = PAGE_SIZE << order;
unsigned int slab_size = (unsigned int)PAGE_SIZE << order;
unsigned int rem;

rem = (slab_size - reserved) % size;

Expand All @@ -3235,12 +3238,11 @@ static inline int slab_order(int size, int min_objects,
return order;
}

static inline int calculate_order(int size, int reserved)
static inline int calculate_order(unsigned int size, unsigned int reserved)
{
int order;
int min_objects;
int fraction;
int max_objects;
unsigned int order;
unsigned int min_objects;
unsigned int max_objects;

/*
* Attempt to find best configuration for a slab. This
Expand All @@ -3257,6 +3259,8 @@ static inline int calculate_order(int size, int reserved)
min_objects = min(min_objects, max_objects);

while (min_objects > 1) {
unsigned int fraction;

fraction = 16;
while (fraction >= 4) {
order = slab_order(size, min_objects,
Expand Down Expand Up @@ -3459,7 +3463,7 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order)
{
slab_flags_t flags = s->flags;
unsigned int size = s->object_size;
int order;
unsigned int order;

/*
* Round up object size to the next word boundary. We can only
Expand Down Expand Up @@ -3549,7 +3553,7 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order)
else
order = calculate_order(size, s->reserved);

if (order < 0)
if ((int)order < 0)
return 0;

s->allocflags = 0;
Expand Down Expand Up @@ -3717,7 +3721,7 @@ int __kmem_cache_shutdown(struct kmem_cache *s)

static int __init setup_slub_min_order(char *str)
{
get_option(&str, &slub_min_order);
get_option(&str, (int *)&slub_min_order);

return 1;
}
Expand All @@ -3726,8 +3730,8 @@ __setup("slub_min_order=", setup_slub_min_order);

static int __init setup_slub_max_order(char *str)
{
get_option(&str, &slub_max_order);
slub_max_order = min(slub_max_order, MAX_ORDER - 1);
get_option(&str, (int *)&slub_max_order);
slub_max_order = min(slub_max_order, (unsigned int)MAX_ORDER - 1);

return 1;
}
Expand All @@ -3736,7 +3740,7 @@ __setup("slub_max_order=", setup_slub_max_order);

static int __init setup_slub_min_objects(char *str)
{
get_option(&str, &slub_min_objects);
get_option(&str, (int *)&slub_min_objects);

return 1;
}
Expand Down Expand Up @@ -4231,7 +4235,7 @@ void __init kmem_cache_init(void)
cpuhp_setup_state_nocalls(CPUHP_SLUB_DEAD, "slub:dead", NULL,
slub_cpu_dead);

pr_info("SLUB: HWalign=%d, Order=%d-%d, MinObjects=%d, CPUs=%u, Nodes=%d\n",
pr_info("SLUB: HWalign=%d, Order=%u-%u, MinObjects=%u, CPUs=%u, Nodes=%d\n",
cache_line_size(),
slub_min_order, slub_max_order, slub_min_objects,
nr_cpu_ids, nr_node_ids);
Expand Down Expand Up @@ -4907,17 +4911,17 @@ SLAB_ATTR_RO(object_size);

static ssize_t objs_per_slab_show(struct kmem_cache *s, char *buf)
{
return sprintf(buf, "%d\n", oo_objects(s->oo));
return sprintf(buf, "%u\n", oo_objects(s->oo));
}
SLAB_ATTR_RO(objs_per_slab);

static ssize_t order_store(struct kmem_cache *s,
const char *buf, size_t length)
{
unsigned long order;
unsigned int order;
int err;

err = kstrtoul(buf, 10, &order);
err = kstrtouint(buf, 10, &order);
if (err)
return err;

Expand All @@ -4930,7 +4934,7 @@ static ssize_t order_store(struct kmem_cache *s,

static ssize_t order_show(struct kmem_cache *s, char *buf)
{
return sprintf(buf, "%d\n", oo_order(s->oo));
return sprintf(buf, "%u\n", oo_order(s->oo));
}
SLAB_ATTR(order);

Expand Down

0 comments on commit 19af27a

Please sign in to comment.