Merge branch 'semaphore' of git://git.kernel.org/pub/scm/linux/kernel/git/willy/misc
[pandora-kernel.git] / mm / slub.c
index 0987d1c..77c21cf 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -5,7 +5,7 @@
  * The allocator synchronizes using per slab locks and only
  * uses a centralized lock to manage a pool of partial slabs.
  *
- * (C) 2007 SGI, Christoph Lameter <clameter@sgi.com>
+ * (C) 2007 SGI, Christoph Lameter
  */
 
 #include <linux/mm.h>
  *                     the fast path and disables lockless freelists.
  */
 
-#define FROZEN (1 << PG_active)
-
 #ifdef CONFIG_SLUB_DEBUG
-#define SLABDEBUG (1 << PG_error)
+#define SLABDEBUG 1
 #else
 #define SLABDEBUG 0
 #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:
  *
@@ -411,7 +379,7 @@ static void set_track(struct kmem_cache *s, void *object,
        if (addr) {
                p->addr = addr;
                p->cpu = smp_processor_id();
-               p->pid = current ? current->pid : -1;
+               p->pid = current->pid;
                p->when = jiffies;
        } else
                memset(p, 0, sizeof(struct track));
@@ -431,9 +399,8 @@ static void print_track(const char *s, struct track *t)
        if (!t->addr)
                return;
 
-       printk(KERN_ERR "INFO: %s in ", s);
-       __print_symbol("%s", (unsigned long)t->addr);
-       printk(" age=%lu cpu=%u pid=%d\n", jiffies - t->when, t->cpu, t->pid);
+       printk(KERN_ERR "INFO: %s in %pS age=%lu cpu=%u pid=%d\n",
+               s, t->addr, jiffies - t->when, t->cpu, t->pid);
 }
 
 static void print_tracking(struct kmem_cache *s, void *object)
@@ -493,7 +460,7 @@ static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p)
        if (p > addr + 16)
                print_section("Bytes b4", p - 16, 16);
 
-       print_section("Object", p, min(s->objsize, 128));
+       print_section("Object", p, min_t(unsigned long, s->objsize, PAGE_SIZE));
 
        if (s->flags & SLAB_RED_ZONE)
                print_section("Redzone", p + s->objsize,
@@ -972,7 +939,7 @@ static int free_debug_processing(struct kmem_cache *s, struct page *page,
        }
 
        /* Special debug activities for freeing objects */
-       if (!SlabFrozen(page) && !page->freelist)
+       if (!PageSlubFrozen(page) && !page->freelist)
                remove_full(s, page);
        if (s->flags & SLAB_STORE_USER)
                set_track(s, object, TRACK_FREE, addr);
@@ -1158,7 +1125,7 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
        page->flags |= 1 << PG_slab;
        if (s->flags & (SLAB_DEBUG_FREE | SLAB_RED_ZONE | SLAB_POISON |
                        SLAB_STORE_USER | SLAB_TRACE))
-               SetSlabDebug(page);
+               __SetPageSlubDebug(page);
 
        start = page_address(page);
 
@@ -1185,14 +1152,14 @@ static void __free_slab(struct kmem_cache *s, struct page *page)
        int order = compound_order(page);
        int pages = 1 << order;
 
-       if (unlikely(SlabDebug(page))) {
+       if (unlikely(SLABDEBUG && PageSlubDebug(page))) {
                void *p;
 
                slab_pad_check(s, page);
                for_each_object(p, s, page_address(page),
                                                page->objects)
                        check_object(s, page, p, 0);
-               ClearSlabDebug(page);
+               __ClearPageSlubDebug(page);
        }
 
        mod_zone_page_state(page_zone(page),
@@ -1289,7 +1256,7 @@ static inline int lock_and_freeze_slab(struct kmem_cache_node *n,
        if (slab_trylock(page)) {
                list_del(&page->lru);
                n->nr_partial--;
-               SetSlabFrozen(page);
+               __SetPageSlubFrozen(page);
                return 1;
        }
        return 0;
@@ -1399,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_cpu *c = get_cpu_slab(s, smp_processor_id());
 
-       ClearSlabFrozen(page);
+       __ClearPageSlubFrozen(page);
        if (page->inuse) {
 
                if (page->freelist) {
@@ -1407,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);
                } else {
                        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);
                }
                slab_unlock(page);
@@ -1496,15 +1464,7 @@ static void flush_cpu_slab(void *d)
 
 static void flush_all(struct kmem_cache *s)
 {
-#ifdef CONFIG_SMP
-       on_each_cpu(flush_cpu_slab, s, 1, 1);
-#else
-       unsigned long flags;
-
-       local_irq_save(flags);
-       flush_cpu_slab(s);
-       local_irq_restore(flags);
-#endif
+       on_each_cpu(flush_cpu_slab, s, 1);
 }
 
 /*
@@ -1560,7 +1520,7 @@ load_freelist:
        object = c->page->freelist;
        if (unlikely(!object))
                goto another_slab;
-       if (unlikely(SlabDebug(c->page)))
+       if (unlikely(SLABDEBUG && PageSlubDebug(c->page)))
                goto debug;
 
        c->freelist = object[c->offset];
@@ -1597,7 +1557,7 @@ new_slab:
                if (c->page)
                        flush_slab(s, c);
                slab_lock(new);
-               SetSlabFrozen(new);
+               __SetPageSlubFrozen(new);
                c->page = new;
                goto load_freelist;
        }
@@ -1628,9 +1588,11 @@ static __always_inline void *slab_alloc(struct kmem_cache *s,
        void **object;
        struct kmem_cache_cpu *c;
        unsigned long flags;
+       unsigned int objsize;
 
        local_irq_save(flags);
        c = get_cpu_slab(s, smp_processor_id());
+       objsize = c->objsize;
        if (unlikely(!c->freelist || !node_match(c, node)))
 
                object = __slab_alloc(s, gfpflags, node, addr, c);
@@ -1643,7 +1605,7 @@ static __always_inline void *slab_alloc(struct kmem_cache *s,
        local_irq_restore(flags);
 
        if (unlikely((gfpflags & __GFP_ZERO) && object))
-               memset(object, 0, c->objsize);
+               memset(object, 0, objsize);
 
        return object;
 }
@@ -1681,7 +1643,7 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
        stat(c, FREE_SLOWPATH);
        slab_lock(page);
 
-       if (unlikely(SlabDebug(page)))
+       if (unlikely(SLABDEBUG && PageSlubDebug(page)))
                goto debug;
 
 checks_ok:
@@ -1689,7 +1651,7 @@ checks_ok:
        page->freelist = object;
        page->inuse--;
 
-       if (unlikely(SlabFrozen(page))) {
+       if (unlikely(PageSlubFrozen(page))) {
                stat(c, FREE_FROZEN);
                goto out_unlock;
        }
@@ -2765,6 +2727,7 @@ void kfree(const void *x)
 
        page = virt_to_head_page(x);
        if (unlikely(!PageSlab(page))) {
+               BUG_ON(!PageCompound(page));
                put_page(page);
                return;
        }
@@ -2995,8 +2958,6 @@ void __init kmem_cache_init(void)
                create_kmalloc_cache(&kmalloc_caches[1],
                                "kmalloc-96", 96, GFP_KERNEL);
                caches++;
-       }
-       if (KMALLOC_MIN_SIZE <= 128) {
                create_kmalloc_cache(&kmalloc_caches[2],
                                "kmalloc-192", 192, GFP_KERNEL);
                caches++;
@@ -3026,6 +2987,16 @@ void __init kmem_cache_init(void)
        for (i = 8; i < KMALLOC_MIN_SIZE; i += 8)
                size_index[(i - 1) / 8] = KMALLOC_SHIFT_LOW;
 
+       if (KMALLOC_MIN_SIZE == 128) {
+               /*
+                * The 192 byte sized cache is not used if the alignment
+                * is 128 byte. Redirect kmalloc to use the 256 byte cache
+                * instead.
+                */
+               for (i = 128 + 8; i <= 192; i += 8)
+                       size_index[(i - 1) / 8] = 8;
+       }
+
        slab_state = UP;
 
        /* Provide the correct kmalloc names now that the caches are up */
@@ -3315,12 +3286,12 @@ static void validate_slab_slab(struct kmem_cache *s, struct page *page,
                        s->name, page);
 
        if (s->flags & DEBUG_DEFAULT_FLAGS) {
-               if (!SlabDebug(page))
-                       printk(KERN_ERR "SLUB %s: SlabDebug not set "
+               if (!PageSlubDebug(page))
+                       printk(KERN_ERR "SLUB %s: SlubDebug not set "
                                "on slab 0x%p\n", s->name, page);
        } else {
-               if (SlabDebug(page))
-                       printk(KERN_ERR "SLUB %s: SlabDebug set on "
+               if (PageSlubDebug(page))
+                       printk(KERN_ERR "SLUB %s: SlubDebug set on "
                                "slab 0x%p\n", s->name, page);
        }
 }