From: Christoph Lameter Subject: Store number of objects in page struct. Split the inuse field up to be able to store the number of objects in this page in the page struct as well. Necessary if we want to have pages of various orders for a slab. Also avoids touching kmem_cache cachelines in __slab_alloc(). Signed-off-by: Christoph Lameter --- include/linux/mm_types.h | 5 ++++- mm/slub.c | 35 ++++++++++++++++++++--------------- 2 files changed, 24 insertions(+), 16 deletions(-) Index: linux-2.6/include/linux/mm_types.h =================================================================== --- linux-2.6.orig/include/linux/mm_types.h 2008-03-16 13:14:53.951657314 -0700 +++ linux-2.6/include/linux/mm_types.h 2008-03-16 13:15:47.776591188 -0700 @@ -42,7 +42,10 @@ struct page { * to show when page is mapped * & limit reverse map searches. */ - unsigned int inuse; /* SLUB: Nr of objects */ + struct { /* SLUB */ + u16 inuse; + u16 objects; + }; }; union { struct { Index: linux-2.6/mm/slub.c =================================================================== --- linux-2.6.orig/mm/slub.c 2008-03-16 13:16:12.217014287 -0700 +++ linux-2.6/mm/slub.c 2008-03-16 13:47:55.081499224 -0700 @@ -301,7 +301,7 @@ static inline int check_valid_pointer(st return 1; base = page_address(page); - if (object < base || object >= base + s->objects * s->size || + if (object < base || object >= base + page->objects * s->size || (object - base) % s->size) { return 0; } @@ -665,7 +665,7 @@ static int slab_pad_check(struct kmem_ca start = page_address(page); end = start + (PAGE_SIZE << s->order); - length = s->objects * s->size; + length = page->objects * s->size; remainder = end - (start + length); if (!remainder) return 1; @@ -745,9 +745,9 @@ static int check_slab(struct kmem_cache slab_err(s, page, "Not a valid slab page"); return 0; } - if (page->inuse > s->objects) { + if (page->inuse > page->objects) { slab_err(s, page, "inuse %u > max %u", - s->name, page->inuse, s->objects); + s->name, page->inuse, page->objects); return 0; } /* Slab_pad_check fixes things up after itself */ @@ -765,7 +765,7 @@ static int on_freelist(struct kmem_cache void *fp = page->freelist; void *object = NULL; - while (fp && nr <= s->objects) { + while (fp && nr <= page->objects) { if (fp == search) return 1; if (!check_valid_pointer(s, page, fp)) { @@ -777,7 +777,7 @@ static int on_freelist(struct kmem_cache } else { slab_err(s, page, "Freepointer corrupt"); page->freelist = NULL; - page->inuse = s->objects; + page->inuse = page->objects; slab_fix(s, "Freelist cleared"); return 0; } @@ -788,10 +788,10 @@ static int on_freelist(struct kmem_cache nr++; } - if (page->inuse != s->objects - nr) { + if (page->inuse != page->objects - nr) { slab_err(s, page, "Wrong object count. Counter is %d but " - "counted were %d", page->inuse, s->objects - nr); - page->inuse = s->objects - nr; + "counted were %d", page->inuse, page->objects - nr); + page->inuse = page->objects - nr; slab_fix(s, "Object count adjusted."); } return search == NULL; @@ -881,7 +881,7 @@ bad: * as used avoids touching the remaining objects. */ slab_fix(s, "Marking all objects used"); - page->inuse = s->objects; + page->inuse = page->objects; page->freelist = NULL; } return 0; @@ -1047,6 +1047,7 @@ static struct page *allocate_slab(struct if (!page) return NULL; + page->objects = s->objects; mod_zone_page_state(page_zone(page), (s->flags & SLAB_RECLAIM_ACCOUNT) ? NR_SLAB_RECLAIMABLE : NR_SLAB_UNRECLAIMABLE, @@ -1487,7 +1488,7 @@ load_freelist: goto debug; c->freelist = object[c->offset]; - c->page->inuse = s->objects; + c->page->inuse = c->page->objects; c->page->freelist = NULL; c->node = page_to_nid(c->page); unlock_out: @@ -2256,7 +2257,11 @@ static int calculate_sizes(struct kmem_c * Determine the number of objects per slab */ s->objects = (PAGE_SIZE << s->order) / size; - + if (s->objects > 65535) { + s->objects = 65535; + printk(KERN_WARNING "slab %s: >65535 objects. " + "Reduced to 65535\n", s->name); + } return !!s->objects; } @@ -3188,7 +3193,7 @@ static int validate_slab(struct kmem_cac return 0; /* Now we know that a valid freelist exists */ - bitmap_zero(map, s->objects); + bitmap_zero(map, page->objects); for_each_free_object(p, s, page->freelist) { set_bit(slab_index(p, s, addr), map); @@ -3465,10 +3470,10 @@ static void process_slab(struct loc_trac struct page *page, enum track_item alloc) { void *addr = page_address(page); - DECLARE_BITMAP(map, s->objects); + DECLARE_BITMAP(map, page->objects); void *p; - bitmap_zero(map, s->objects); + bitmap_zero(map, page->objects); for_each_free_object(p, s, page->freelist) set_bit(slab_index(p, s, addr), map);