SLUB: Simplify debug code
Consolidate functionality into the #ifdef section. Extract tracing into one subroutine. Move object debug processing into the #ifdef section so that the code in __slab_alloc and __slab_free becomes minimal. Reduce number of functions we need to provide stubs for in the !SLUB_DEBUG case. Signed-off-by: Christoph Lameter <clameter@sgi.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Родитель
a35afb830f
Коммит
3ec0974210
112
mm/slub.c
112
mm/slub.c
|
@ -742,6 +742,22 @@ static int on_freelist(struct kmem_cache *s, struct page *page, void *search)
|
|||
return search == NULL;
|
||||
}
|
||||
|
||||
static void trace(struct kmem_cache *s, struct page *page, void *object, int alloc)
|
||||
{
|
||||
if (s->flags & SLAB_TRACE) {
|
||||
printk(KERN_INFO "TRACE %s %s 0x%p inuse=%d fp=0x%p\n",
|
||||
s->name,
|
||||
alloc ? "alloc" : "free",
|
||||
object, page->inuse,
|
||||
page->freelist);
|
||||
|
||||
if (!alloc)
|
||||
print_section("Object", (void *)object, s->objsize);
|
||||
|
||||
dump_stack();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Tracking of fully allocated slabs for debugging purposes.
|
||||
*/
|
||||
|
@ -766,8 +782,18 @@ static void remove_full(struct kmem_cache *s, struct page *page)
|
|||
spin_unlock(&n->list_lock);
|
||||
}
|
||||
|
||||
static int alloc_object_checks(struct kmem_cache *s, struct page *page,
|
||||
void *object)
|
||||
static void setup_object_debug(struct kmem_cache *s, struct page *page,
|
||||
void *object)
|
||||
{
|
||||
if (!(s->flags & (SLAB_STORE_USER|SLAB_RED_ZONE|__OBJECT_POISON)))
|
||||
return;
|
||||
|
||||
init_object(s, object, 0);
|
||||
init_tracking(s, object);
|
||||
}
|
||||
|
||||
static int alloc_debug_processing(struct kmem_cache *s, struct page *page,
|
||||
void *object, void *addr)
|
||||
{
|
||||
if (!check_slab(s, page))
|
||||
goto bad;
|
||||
|
@ -782,13 +808,16 @@ static int alloc_object_checks(struct kmem_cache *s, struct page *page,
|
|||
goto bad;
|
||||
}
|
||||
|
||||
if (!object)
|
||||
return 1;
|
||||
|
||||
if (!check_object(s, page, object, 0))
|
||||
if (object && !check_object(s, page, object, 0))
|
||||
goto bad;
|
||||
|
||||
/* Success perform special debug activities for allocs */
|
||||
if (s->flags & SLAB_STORE_USER)
|
||||
set_track(s, object, TRACK_ALLOC, addr);
|
||||
trace(s, page, object, 1);
|
||||
init_object(s, object, 1);
|
||||
return 1;
|
||||
|
||||
bad:
|
||||
if (PageSlab(page)) {
|
||||
/*
|
||||
|
@ -806,8 +835,8 @@ bad:
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int free_object_checks(struct kmem_cache *s, struct page *page,
|
||||
void *object)
|
||||
static int free_debug_processing(struct kmem_cache *s, struct page *page,
|
||||
void *object, void *addr)
|
||||
{
|
||||
if (!check_slab(s, page))
|
||||
goto fail;
|
||||
|
@ -841,29 +870,22 @@ static int free_object_checks(struct kmem_cache *s, struct page *page,
|
|||
"to slab %s", object, page->slab->name);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Special debug activities for freeing objects */
|
||||
if (!SlabFrozen(page) && !page->freelist)
|
||||
remove_full(s, page);
|
||||
if (s->flags & SLAB_STORE_USER)
|
||||
set_track(s, object, TRACK_FREE, addr);
|
||||
trace(s, page, object, 0);
|
||||
init_object(s, object, 0);
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
printk(KERN_ERR "@@@ SLUB: %s slab 0x%p object at 0x%p not freed.\n",
|
||||
s->name, page, object);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void trace(struct kmem_cache *s, struct page *page, void *object, int alloc)
|
||||
{
|
||||
if (s->flags & SLAB_TRACE) {
|
||||
printk(KERN_INFO "TRACE %s %s 0x%p inuse=%d fp=0x%p\n",
|
||||
s->name,
|
||||
alloc ? "alloc" : "free",
|
||||
object, page->inuse,
|
||||
page->freelist);
|
||||
|
||||
if (!alloc)
|
||||
print_section("Object", (void *)object, s->objsize);
|
||||
|
||||
dump_stack();
|
||||
}
|
||||
}
|
||||
|
||||
static int __init setup_slub_debug(char *str)
|
||||
{
|
||||
if (!str || *str != '=')
|
||||
|
@ -932,26 +954,20 @@ static void kmem_cache_open_debug_check(struct kmem_cache *s)
|
|||
s->flags |= slub_debug;
|
||||
}
|
||||
#else
|
||||
static inline void setup_object_debug(struct kmem_cache *s,
|
||||
struct page *page, void *object) {}
|
||||
|
||||
static inline int alloc_object_checks(struct kmem_cache *s,
|
||||
struct page *page, void *object) { return 0; }
|
||||
static inline int alloc_debug_processing(struct kmem_cache *s,
|
||||
struct page *page, void *object, void *addr) { return 0; }
|
||||
|
||||
static inline int free_object_checks(struct kmem_cache *s,
|
||||
struct page *page, void *object) { return 0; }
|
||||
static inline int free_debug_processing(struct kmem_cache *s,
|
||||
struct page *page, void *object, void *addr) { return 0; }
|
||||
|
||||
static inline void add_full(struct kmem_cache_node *n, struct page *page) {}
|
||||
static inline void remove_full(struct kmem_cache *s, struct page *page) {}
|
||||
static inline void trace(struct kmem_cache *s, struct page *page,
|
||||
void *object, int alloc) {}
|
||||
static inline void init_object(struct kmem_cache *s,
|
||||
void *object, int active) {}
|
||||
static inline void init_tracking(struct kmem_cache *s, void *object) {}
|
||||
static inline int slab_pad_check(struct kmem_cache *s, struct page *page)
|
||||
{ return 1; }
|
||||
static inline int check_object(struct kmem_cache *s, struct page *page,
|
||||
void *object, int active) { return 1; }
|
||||
static inline void set_track(struct kmem_cache *s, void *object,
|
||||
enum track_item alloc, void *addr) {}
|
||||
static inline void add_full(struct kmem_cache_node *n, struct page *page) {}
|
||||
static inline void kmem_cache_open_debug_check(struct kmem_cache *s) {}
|
||||
#define slub_debug 0
|
||||
#endif
|
||||
|
@ -988,11 +1004,7 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)
|
|||
static void setup_object(struct kmem_cache *s, struct page *page,
|
||||
void *object)
|
||||
{
|
||||
if (SlabDebug(page)) {
|
||||
init_object(s, object, 0);
|
||||
init_tracking(s, object);
|
||||
}
|
||||
|
||||
setup_object_debug(s, page, object);
|
||||
if (unlikely(s->ctor))
|
||||
s->ctor(object, s, 0);
|
||||
}
|
||||
|
@ -1449,12 +1461,8 @@ new_slab:
|
|||
return NULL;
|
||||
debug:
|
||||
object = page->freelist;
|
||||
if (!alloc_object_checks(s, page, object))
|
||||
if (!alloc_debug_processing(s, page, object, addr))
|
||||
goto another_slab;
|
||||
if (s->flags & SLAB_STORE_USER)
|
||||
set_track(s, object, TRACK_ALLOC, addr);
|
||||
trace(s, page, object, 1);
|
||||
init_object(s, object, 1);
|
||||
|
||||
page->inuse++;
|
||||
page->freelist = object[page->offset];
|
||||
|
@ -1561,14 +1569,8 @@ slab_empty:
|
|||
return;
|
||||
|
||||
debug:
|
||||
if (!free_object_checks(s, page, x))
|
||||
if (!free_debug_processing(s, page, x, addr))
|
||||
goto out_unlock;
|
||||
if (!SlabFrozen(page) && !page->freelist)
|
||||
remove_full(s, page);
|
||||
if (s->flags & SLAB_STORE_USER)
|
||||
set_track(s, x, TRACK_FREE, addr);
|
||||
trace(s, page, object, 0);
|
||||
init_object(s, object, 0);
|
||||
goto checks_ok;
|
||||
}
|
||||
|
||||
|
@ -1805,7 +1807,7 @@ static struct kmem_cache_node * __init early_kmem_cache_node_alloc(gfp_t gfpflag
|
|||
page->freelist = get_freepointer(kmalloc_caches, n);
|
||||
page->inuse++;
|
||||
kmalloc_caches->node[node] = n;
|
||||
init_object(kmalloc_caches, n, 1);
|
||||
setup_object_debug(kmalloc_caches, page, n);
|
||||
init_kmem_cache_node(n);
|
||||
atomic_long_inc(&n->nr_slabs);
|
||||
add_partial(n, page);
|
||||
|
|
Загрузка…
Ссылка в новой задаче