Commit 68dff6a9 authored by Christoph Lameter's avatar Christoph Lameter Committed by Linus Torvalds

SLUB slab validation: Move tracking information alloc outside of lock

We currently have to do an GFP_ATOMIC allocation because the list_lock is
already taken when we first allocate memory for tracking allocation
information.  It would be better if we could avoid atomic allocations.

Allocate a size of the tracking table that is usually sufficient (one page)
before we take the list lock.  We will then only do the atomic allocation
if we need to resize the table to become larger than a page (mostly only
needed under large NUMA because of the tracking of cpus and nodes otherwise
the table stays small).
Signed-off-by: default avatarChristoph Lameter <clameter@sgi.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 5b95a4ac
...@@ -2902,18 +2902,14 @@ static void free_loc_track(struct loc_track *t) ...@@ -2902,18 +2902,14 @@ static void free_loc_track(struct loc_track *t)
get_order(sizeof(struct location) * t->max)); get_order(sizeof(struct location) * t->max));
} }
static int alloc_loc_track(struct loc_track *t, unsigned long max) static int alloc_loc_track(struct loc_track *t, unsigned long max, gfp_t flags)
{ {
struct location *l; struct location *l;
int order; int order;
if (!max)
max = PAGE_SIZE / sizeof(struct location);
order = get_order(sizeof(struct location) * max); order = get_order(sizeof(struct location) * max);
l = (void *)__get_free_pages(GFP_ATOMIC, order); l = (void *)__get_free_pages(flags, order);
if (!l) if (!l)
return 0; return 0;
...@@ -2979,7 +2975,7 @@ static int add_location(struct loc_track *t, struct kmem_cache *s, ...@@ -2979,7 +2975,7 @@ static int add_location(struct loc_track *t, struct kmem_cache *s,
/* /*
* Not found. Insert new tracking element. * Not found. Insert new tracking element.
*/ */
if (t->count >= t->max && !alloc_loc_track(t, 2 * t->max)) if (t->count >= t->max && !alloc_loc_track(t, 2 * t->max, GFP_ATOMIC))
return 0; return 0;
l = t->loc + pos; l = t->loc + pos;
...@@ -3022,11 +3018,12 @@ static int list_locations(struct kmem_cache *s, char *buf, ...@@ -3022,11 +3018,12 @@ static int list_locations(struct kmem_cache *s, char *buf,
{ {
int n = 0; int n = 0;
unsigned long i; unsigned long i;
struct loc_track t; struct loc_track t = { 0, 0, NULL };
int node; int node;
t.count = 0; if (!alloc_loc_track(&t, PAGE_SIZE / sizeof(struct location),
t.max = 0; GFP_KERNEL))
return sprintf(buf, "Out of memory\n");
/* Push back cpu slabs */ /* Push back cpu slabs */
flush_all(s); flush_all(s);
......
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