slub: record page flag overlays explicitly

SLUB reuses two page bits for internal purposes, it overlays PG_active and
PG_error.  This is hidden away in slub.c.  Document these overlays
explicitly in the main page-flags enum along with all the others.

Signed-off-by: Andy Whitcroft <apw@shadowen.org>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: Christoph Lameter <cl@linux-foundation.org>
Cc: Matt Mackall <mpm@selenic.com>
Cc: Nick Piggin <nickpiggin@yahoo.com.au>
Tested-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: Rik van Riel <riel@redhat.com>
Cc: Jeremy Fitzhardinge <jeremy@goop.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Andy Whitcroft 2008-07-23 21:27:18 -07:00 committed by Linus Torvalds
parent 0cad47cf13
commit 8a38082d21
2 changed files with 24 additions and 48 deletions

View File

@ -104,6 +104,10 @@ enum pageflags {
/* XEN */ /* XEN */
PG_pinned = PG_owner_priv_1, PG_pinned = PG_owner_priv_1,
PG_savepinned = PG_dirty, PG_savepinned = PG_dirty,
/* SLUB */
PG_slub_frozen = PG_active,
PG_slub_debug = PG_error,
}; };
#ifndef __GENERATING_BOUNDS_H #ifndef __GENERATING_BOUNDS_H
@ -169,6 +173,9 @@ PAGEFLAG(Reserved, reserved) __CLEARPAGEFLAG(Reserved, reserved)
PAGEFLAG(Private, private) __CLEARPAGEFLAG(Private, private) PAGEFLAG(Private, private) __CLEARPAGEFLAG(Private, private)
__SETPAGEFLAG(Private, private) __SETPAGEFLAG(Private, private)
__PAGEFLAG(SlubFrozen, slub_frozen)
__PAGEFLAG(SlubDebug, slub_debug)
/* /*
* Only test-and-set exist for PG_writeback. The unconditional operators are * Only test-and-set exist for PG_writeback. The unconditional operators are
* risky: they bypass page accounting. * risky: they bypass page accounting.

View File

@ -102,44 +102,12 @@
* the fast path and disables lockless freelists. * the fast path and disables lockless freelists.
*/ */
#define FROZEN (1 << PG_active)
#ifdef CONFIG_SLUB_DEBUG #ifdef CONFIG_SLUB_DEBUG
#define SLABDEBUG (1 << PG_error) #define SLABDEBUG 1
#else #else
#define SLABDEBUG 0 #define SLABDEBUG 0
#endif #endif
static inline int SlabFrozen(struct page *page)
{
return page->flags & FROZEN;
}
static inline void SetSlabFrozen(struct page *page)
{
page->flags |= FROZEN;
}
static inline void ClearSlabFrozen(struct page *page)
{
page->flags &= ~FROZEN;
}
static inline int SlabDebug(struct page *page)
{
return page->flags & SLABDEBUG;
}
static inline void SetSlabDebug(struct page *page)
{
page->flags |= SLABDEBUG;
}
static inline void ClearSlabDebug(struct page *page)
{
page->flags &= ~SLABDEBUG;
}
/* /*
* Issues still to be resolved: * Issues still to be resolved:
* *
@ -971,7 +939,7 @@ static int free_debug_processing(struct kmem_cache *s, struct page *page,
} }
/* Special debug activities for freeing objects */ /* Special debug activities for freeing objects */
if (!SlabFrozen(page) && !page->freelist) if (!PageSlubFrozen(page) && !page->freelist)
remove_full(s, page); remove_full(s, page);
if (s->flags & SLAB_STORE_USER) if (s->flags & SLAB_STORE_USER)
set_track(s, object, TRACK_FREE, addr); set_track(s, object, TRACK_FREE, addr);
@ -1157,7 +1125,7 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
page->flags |= 1 << PG_slab; page->flags |= 1 << PG_slab;
if (s->flags & (SLAB_DEBUG_FREE | SLAB_RED_ZONE | SLAB_POISON | if (s->flags & (SLAB_DEBUG_FREE | SLAB_RED_ZONE | SLAB_POISON |
SLAB_STORE_USER | SLAB_TRACE)) SLAB_STORE_USER | SLAB_TRACE))
SetSlabDebug(page); __SetPageSlubDebug(page);
start = page_address(page); start = page_address(page);
@ -1184,14 +1152,14 @@ static void __free_slab(struct kmem_cache *s, struct page *page)
int order = compound_order(page); int order = compound_order(page);
int pages = 1 << order; int pages = 1 << order;
if (unlikely(SlabDebug(page))) { if (unlikely(SLABDEBUG && PageSlubDebug(page))) {
void *p; void *p;
slab_pad_check(s, page); slab_pad_check(s, page);
for_each_object(p, s, page_address(page), for_each_object(p, s, page_address(page),
page->objects) page->objects)
check_object(s, page, p, 0); check_object(s, page, p, 0);
ClearSlabDebug(page); __ClearPageSlubDebug(page);
} }
mod_zone_page_state(page_zone(page), mod_zone_page_state(page_zone(page),
@ -1288,7 +1256,7 @@ static inline int lock_and_freeze_slab(struct kmem_cache_node *n,
if (slab_trylock(page)) { if (slab_trylock(page)) {
list_del(&page->lru); list_del(&page->lru);
n->nr_partial--; n->nr_partial--;
SetSlabFrozen(page); __SetPageSlubFrozen(page);
return 1; return 1;
} }
return 0; return 0;
@ -1398,7 +1366,7 @@ static void unfreeze_slab(struct kmem_cache *s, struct page *page, int tail)
struct kmem_cache_node *n = get_node(s, page_to_nid(page)); struct kmem_cache_node *n = get_node(s, page_to_nid(page));
struct kmem_cache_cpu *c = get_cpu_slab(s, smp_processor_id()); struct kmem_cache_cpu *c = get_cpu_slab(s, smp_processor_id());
ClearSlabFrozen(page); __ClearPageSlubFrozen(page);
if (page->inuse) { if (page->inuse) {
if (page->freelist) { if (page->freelist) {
@ -1406,7 +1374,8 @@ static void unfreeze_slab(struct kmem_cache *s, struct page *page, int tail)
stat(c, tail ? DEACTIVATE_TO_TAIL : DEACTIVATE_TO_HEAD); stat(c, tail ? DEACTIVATE_TO_TAIL : DEACTIVATE_TO_HEAD);
} else { } else {
stat(c, DEACTIVATE_FULL); stat(c, DEACTIVATE_FULL);
if (SlabDebug(page) && (s->flags & SLAB_STORE_USER)) if (SLABDEBUG && PageSlubDebug(page) &&
(s->flags & SLAB_STORE_USER))
add_full(n, page); add_full(n, page);
} }
slab_unlock(page); slab_unlock(page);
@ -1551,7 +1520,7 @@ load_freelist:
object = c->page->freelist; object = c->page->freelist;
if (unlikely(!object)) if (unlikely(!object))
goto another_slab; goto another_slab;
if (unlikely(SlabDebug(c->page))) if (unlikely(SLABDEBUG && PageSlubDebug(c->page)))
goto debug; goto debug;
c->freelist = object[c->offset]; c->freelist = object[c->offset];
@ -1588,7 +1557,7 @@ new_slab:
if (c->page) if (c->page)
flush_slab(s, c); flush_slab(s, c);
slab_lock(new); slab_lock(new);
SetSlabFrozen(new); __SetPageSlubFrozen(new);
c->page = new; c->page = new;
goto load_freelist; goto load_freelist;
} }
@ -1674,7 +1643,7 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
stat(c, FREE_SLOWPATH); stat(c, FREE_SLOWPATH);
slab_lock(page); slab_lock(page);
if (unlikely(SlabDebug(page))) if (unlikely(SLABDEBUG && PageSlubDebug(page)))
goto debug; goto debug;
checks_ok: checks_ok:
@ -1682,7 +1651,7 @@ checks_ok:
page->freelist = object; page->freelist = object;
page->inuse--; page->inuse--;
if (unlikely(SlabFrozen(page))) { if (unlikely(PageSlubFrozen(page))) {
stat(c, FREE_FROZEN); stat(c, FREE_FROZEN);
goto out_unlock; goto out_unlock;
} }
@ -3317,12 +3286,12 @@ static void validate_slab_slab(struct kmem_cache *s, struct page *page,
s->name, page); s->name, page);
if (s->flags & DEBUG_DEFAULT_FLAGS) { if (s->flags & DEBUG_DEFAULT_FLAGS) {
if (!SlabDebug(page)) if (!PageSlubDebug(page))
printk(KERN_ERR "SLUB %s: SlabDebug not set " printk(KERN_ERR "SLUB %s: SlubDebug not set "
"on slab 0x%p\n", s->name, page); "on slab 0x%p\n", s->name, page);
} else { } else {
if (SlabDebug(page)) if (PageSlubDebug(page))
printk(KERN_ERR "SLUB %s: SlabDebug set on " printk(KERN_ERR "SLUB %s: SlubDebug set on "
"slab 0x%p\n", s->name, page); "slab 0x%p\n", s->name, page);
} }
} }