[PATCH] slab: extract slab order calculation to separate function
This patch moves the ugly loop that determines the 'optimal' size (page order) of cache slabs from kmem_cache_create() to a separate function and cleans it up a bit. Thanks to Matthew Wilcox for the help with this patch. Signed-off-by: Matthew Dobson <colpatch@us.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
85289f98dd
commit
4d268eba11
1 changed files with 49 additions and 40 deletions
89
mm/slab.c
89
mm/slab.c
|
@ -1473,6 +1473,53 @@ static inline void set_up_list3s(kmem_cache_t *cachep, int index)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* calculate_slab_order - calculate size (page order) of slabs and the number
|
||||
* of objects per slab.
|
||||
*
|
||||
* This could be made much more intelligent. For now, try to avoid using
|
||||
* high order pages for slabs. When the gfp() functions are more friendly
|
||||
* towards high-order requests, this should be changed.
|
||||
*/
|
||||
static inline size_t calculate_slab_order(kmem_cache_t *cachep, size_t size,
|
||||
size_t align, gfp_t flags)
|
||||
{
|
||||
size_t left_over = 0;
|
||||
|
||||
for ( ; ; cachep->gfporder++) {
|
||||
unsigned int num;
|
||||
size_t remainder;
|
||||
|
||||
if (cachep->gfporder > MAX_GFP_ORDER) {
|
||||
cachep->num = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
cache_estimate(cachep->gfporder, size, align, flags,
|
||||
&remainder, &num);
|
||||
if (!num)
|
||||
continue;
|
||||
/* More than offslab_limit objects will cause problems */
|
||||
if (flags & CFLGS_OFF_SLAB && cachep->num > offslab_limit)
|
||||
break;
|
||||
|
||||
cachep->num = num;
|
||||
left_over = remainder;
|
||||
|
||||
/*
|
||||
* Large number of objects is good, but very large slabs are
|
||||
* currently bad for the gfp()s.
|
||||
*/
|
||||
if (cachep->gfporder >= slab_break_gfp_order)
|
||||
break;
|
||||
|
||||
if ((left_over * 8) <= (PAGE_SIZE << cachep->gfporder))
|
||||
/* Acceptable internal fragmentation */
|
||||
break;
|
||||
}
|
||||
return left_over;
|
||||
}
|
||||
|
||||
/**
|
||||
* kmem_cache_create - Create a cache.
|
||||
* @name: A string which is used in /proc/slabinfo to identify this cache.
|
||||
|
@ -1682,46 +1729,8 @@ kmem_cache_create (const char *name, size_t size, size_t align,
|
|||
cachep->gfporder = 0;
|
||||
cache_estimate(cachep->gfporder, size, align, flags,
|
||||
&left_over, &cachep->num);
|
||||
} else {
|
||||
/*
|
||||
* Calculate size (in pages) of slabs, and the num of objs per
|
||||
* slab. This could be made much more intelligent. For now,
|
||||
* try to avoid using high page-orders for slabs. When the
|
||||
* gfp() funcs are more friendly towards high-order requests,
|
||||
* this should be changed.
|
||||
*/
|
||||
do {
|
||||
unsigned int break_flag = 0;
|
||||
cal_wastage:
|
||||
cache_estimate(cachep->gfporder, size, align, flags,
|
||||
&left_over, &cachep->num);
|
||||
if (break_flag)
|
||||
break;
|
||||
if (cachep->gfporder >= MAX_GFP_ORDER)
|
||||
break;
|
||||
if (!cachep->num)
|
||||
goto next;
|
||||
if (flags & CFLGS_OFF_SLAB &&
|
||||
cachep->num > offslab_limit) {
|
||||
/* This num of objs will cause problems. */
|
||||
cachep->gfporder--;
|
||||
break_flag++;
|
||||
goto cal_wastage;
|
||||
}
|
||||
|
||||
/*
|
||||
* Large num of objs is good, but v. large slabs are
|
||||
* currently bad for the gfp()s.
|
||||
*/
|
||||
if (cachep->gfporder >= slab_break_gfp_order)
|
||||
break;
|
||||
|
||||
if ((left_over*8) <= (PAGE_SIZE<<cachep->gfporder))
|
||||
break; /* Acceptable internal fragmentation. */
|
||||
next:
|
||||
cachep->gfporder++;
|
||||
} while (1);
|
||||
}
|
||||
} else
|
||||
left_over = calculate_slab_order(cachep, size, align, flags);
|
||||
|
||||
if (!cachep->num) {
|
||||
printk("kmem_cache_create: couldn't create cache %s.\n", name);
|
||||
|
|
Loading…
Reference in a new issue