From ee3558391289934c28a321c3abc95e5cc27f767b Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 9 May 2007 02:32:46 -0700 Subject: [PATCH] --- yaml --- r: 55290 b: refs/heads/master c: 5e6d444ea1f72b8148354a9baf0ea8fa3dd0425b h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/mm/slub.c | 66 ++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 53 insertions(+), 15 deletions(-) diff --git a/[refs] b/[refs] index 60bbfe55c81d..0da57e59d9c3 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 45edfa580b8e638c44ec26872bfe75b307ba12d1 +refs/heads/master: 5e6d444ea1f72b8148354a9baf0ea8fa3dd0425b diff --git a/trunk/mm/slub.c b/trunk/mm/slub.c index ae2831027802..c81f52a72153 100644 --- a/trunk/mm/slub.c +++ b/trunk/mm/slub.c @@ -1577,37 +1577,75 @@ static int slub_nomerge; * requested a higher mininum order then we start with that one instead of * the smallest order which will fit the object. */ -static int calculate_order(int size) +static inline int slab_order(int size, int min_objects, + int max_order, int fract_leftover) { int order; int rem; - for (order = max(slub_min_order, fls(size - 1) - PAGE_SHIFT); - order < MAX_ORDER; order++) { - unsigned long slab_size = PAGE_SIZE << order; + for (order = max(slub_min_order, + fls(min_objects * size - 1) - PAGE_SHIFT); + order <= max_order; order++) { - if (order < slub_max_order && - slab_size < slub_min_objects * size) - continue; + unsigned long slab_size = PAGE_SIZE << order; - if (slab_size < size) + if (slab_size < min_objects * size) continue; - if (order >= slub_max_order) - break; - rem = slab_size % size; - if (rem <= slab_size / 8) + if (rem <= slab_size / fract_leftover) break; } - if (order >= MAX_ORDER) - return -E2BIG; return order; } +static inline int calculate_order(int size) +{ + int order; + int min_objects; + int fraction; + + /* + * Attempt to find best configuration for a slab. This + * works by first attempting to generate a layout with + * the best configuration and backing off gradually. + * + * First we reduce the acceptable waste in a slab. Then + * we reduce the minimum objects required in a slab. + */ + min_objects = slub_min_objects; + while (min_objects > 1) { + fraction = 8; + while (fraction >= 4) { + order = slab_order(size, min_objects, + slub_max_order, fraction); + if (order <= slub_max_order) + return order; + fraction /= 2; + } + min_objects /= 2; + } + + /* + * We were unable to place multiple objects in a slab. Now + * lets see if we can place a single object there. + */ + order = slab_order(size, 1, slub_max_order, 1); + if (order <= slub_max_order) + return order; + + /* + * Doh this slab cannot be placed using slub_max_order. + */ + order = slab_order(size, 1, MAX_ORDER, 1); + if (order <= MAX_ORDER) + return order; + return -ENOSYS; +} + /* * Figure out what the alignment of the objects will be. */