mm/slab: use more appropriate condition check for debug_pagealloc
[linux-2.6-block.git] / mm / slab.c
index 6ecc697a8bc4670a3910fdcdc155196ee71a539a..8bca9be5d557dfce6072c202d2e5ca9ed3cfd0ec 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -224,16 +224,6 @@ static inline void clear_obj_pfmemalloc(void **objp)
        *objp = (void *)((unsigned long)*objp & ~SLAB_OBJ_PFMEMALLOC);
 }
 
-/*
- * bootstrap: The caches do not work without cpuarrays anymore, but the
- * cpuarrays are allocated from the generic caches...
- */
-#define BOOT_CPUCACHE_ENTRIES  1
-struct arraycache_init {
-       struct array_cache cache;
-       void *entries[BOOT_CPUCACHE_ENTRIES];
-};
-
 /*
  * Need this for bootstrapping a per node allocator.
  */
@@ -457,6 +447,7 @@ static inline unsigned int obj_to_index(const struct kmem_cache *cache,
        return reciprocal_divide(offset, cache->reciprocal_buffer_size);
 }
 
+#define BOOT_CPUCACHE_ENTRIES  1
 /* internal cache of cache description objs */
 static struct kmem_cache kmem_cache_boot = {
        .batchcount = 1,
@@ -537,7 +528,7 @@ static void cache_estimate(unsigned long gfporder, size_t buffer_size,
         * on it. For the latter case, the memory allocated for a
         * slab is used for:
         *
-        * - One unsigned int for each object
+        * - One freelist_idx_t for each object
         * - Padding to respect alignment of @align
         * - @buffer_size bytes for each object
         *
@@ -1847,7 +1838,8 @@ static void slab_destroy_debugcheck(struct kmem_cache *cachep,
 
                if (cachep->flags & SLAB_POISON) {
 #ifdef CONFIG_DEBUG_PAGEALLOC
-                       if (cachep->size % PAGE_SIZE == 0 &&
+                       if (debug_pagealloc_enabled() &&
+                               cachep->size % PAGE_SIZE == 0 &&
                                        OFF_SLAB(cachep))
                                kernel_map_pages(virt_to_page(objp),
                                        cachep->size / PAGE_SIZE, 1);
@@ -2119,8 +2111,6 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags)
        if (!(flags & SLAB_DESTROY_BY_RCU))
                flags |= SLAB_POISON;
 #endif
-       if (flags & SLAB_DESTROY_BY_RCU)
-               BUG_ON(flags & SLAB_POISON);
 #endif
 
        /*
@@ -2179,7 +2169,6 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags)
                else
                        size += BYTES_PER_WORD;
        }
-#if FORCED_DEBUG && defined(CONFIG_DEBUG_PAGEALLOC)
        /*
         * To activate debug pagealloc, off-slab management is necessary
         * requirement. In early phase of initialization, small sized slab
@@ -2187,13 +2176,13 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags)
         * to check size >= 256. It guarantees that all necessary small
         * sized slab is initialized in current slab initialization sequence.
         */
-       if (!slab_early_init && size >= kmalloc_size(INDEX_NODE) &&
+       if (debug_pagealloc_enabled() && (flags & SLAB_POISON) &&
+               !slab_early_init && size >= kmalloc_size(INDEX_NODE) &&
                size >= 256 && cachep->object_size > cache_line_size() &&
                ALIGN(size, cachep->align) < PAGE_SIZE) {
                cachep->obj_offset += PAGE_SIZE - ALIGN(size, cachep->align);
                size = PAGE_SIZE;
        }
-#endif
 #endif
 
        /*
@@ -2243,7 +2232,8 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags)
                 * poisoning, then it's going to smash the contents of
                 * the redzone and userword anyhow, so switch them off.
                 */
-               if (size % PAGE_SIZE == 0 && flags & SLAB_POISON)
+               if (debug_pagealloc_enabled() &&
+                       size % PAGE_SIZE == 0 && flags & SLAB_POISON)
                        flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER);
 #endif
        }
@@ -2275,7 +2265,7 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags)
 
        err = setup_cpu_cache(cachep, gfp);
        if (err) {
-               __kmem_cache_shutdown(cachep);
+               __kmem_cache_release(cachep);
                return err;
        }
 
@@ -2377,9 +2367,6 @@ static int drain_freelist(struct kmem_cache *cache,
                }
 
                page = list_entry(p, struct page, lru);
-#if DEBUG
-               BUG_ON(page->active);
-#endif
                list_del(&page->lru);
                /*
                 * Safe to drop the lock. The slab is no longer linked
@@ -2413,13 +2400,14 @@ int __kmem_cache_shrink(struct kmem_cache *cachep, bool deactivate)
 }
 
 int __kmem_cache_shutdown(struct kmem_cache *cachep)
+{
+       return __kmem_cache_shrink(cachep, false);
+}
+
+void __kmem_cache_release(struct kmem_cache *cachep)
 {
        int i;
        struct kmem_cache_node *n;
-       int rc = __kmem_cache_shrink(cachep, false);
-
-       if (rc)
-               return rc;
 
        free_percpu(cachep->cpu_cache);
 
@@ -2430,7 +2418,6 @@ int __kmem_cache_shutdown(struct kmem_cache *cachep)
                kfree(n);
                cachep->node[i] = NULL;
        }
-       return 0;
 }
 
 /*
@@ -2537,30 +2524,23 @@ static void kmem_flagcheck(struct kmem_cache *cachep, gfp_t flags)
        }
 }
 
-static void *slab_get_obj(struct kmem_cache *cachep, struct page *page,
-                               int nodeid)
+static void *slab_get_obj(struct kmem_cache *cachep, struct page *page)
 {
        void *objp;
 
        objp = index_to_obj(cachep, page, get_free_obj(page, page->active));
        page->active++;
-#if DEBUG
-       WARN_ON(page_to_nid(virt_to_page(objp)) != nodeid);
-#endif
 
        return objp;
 }
 
-static void slab_put_obj(struct kmem_cache *cachep, struct page *page,
-                               void *objp, int nodeid)
+static void slab_put_obj(struct kmem_cache *cachep,
+                       struct page *page, void *objp)
 {
        unsigned int objnr = obj_to_index(cachep, page, objp);
 #if DEBUG
        unsigned int i;
 
-       /* Verify that the slab belongs to the intended node */
-       WARN_ON(page_to_nid(virt_to_page(objp)) != nodeid);
-
        /* Verify double free bug */
        for (i = page->active; i < cachep->num; i++) {
                if (get_free_obj(page, i) == objnr) {
@@ -2737,7 +2717,8 @@ static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp,
        set_obj_status(page, objnr, OBJECT_FREE);
        if (cachep->flags & SLAB_POISON) {
 #ifdef CONFIG_DEBUG_PAGEALLOC
-               if ((cachep->size % PAGE_SIZE)==0 && OFF_SLAB(cachep)) {
+               if (debug_pagealloc_enabled() &&
+                       (cachep->size % PAGE_SIZE) == 0 && OFF_SLAB(cachep)) {
                        store_stackinfo(cachep, objp, caller);
                        kernel_map_pages(virt_to_page(objp),
                                         cachep->size / PAGE_SIZE, 0);
@@ -2826,8 +2807,7 @@ retry:
                        STATS_INC_ACTIVE(cachep);
                        STATS_SET_HIGH(cachep);
 
-                       ac_put_obj(cachep, ac, slab_get_obj(cachep, page,
-                                                                       node));
+                       ac_put_obj(cachep, ac, slab_get_obj(cachep, page));
                }
 
                /* move slabp to correct slabp list: */
@@ -2883,7 +2863,8 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep,
                return objp;
        if (cachep->flags & SLAB_POISON) {
 #ifdef CONFIG_DEBUG_PAGEALLOC
-               if ((cachep->size % PAGE_SIZE) == 0 && OFF_SLAB(cachep))
+               if (debug_pagealloc_enabled() &&
+                       (cachep->size % PAGE_SIZE) == 0 && OFF_SLAB(cachep))
                        kernel_map_pages(virt_to_page(objp),
                                         cachep->size / PAGE_SIZE, 1);
                else
@@ -2926,14 +2907,6 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep,
 #define cache_alloc_debugcheck_after(a,b,objp,d) (objp)
 #endif
 
-static bool slab_should_failslab(struct kmem_cache *cachep, gfp_t flags)
-{
-       if (unlikely(cachep == kmem_cache))
-               return false;
-
-       return should_failslab(cachep->object_size, flags, cachep->flags);
-}
-
 static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags)
 {
        void *objp;
@@ -3118,7 +3091,7 @@ retry:
 
        BUG_ON(page->active == cachep->num);
 
-       obj = slab_get_obj(cachep, page, nodeid);
+       obj = slab_get_obj(cachep, page);
        n->free_objects--;
        /* move slabp to correct slabp list: */
        list_del(&page->lru);
@@ -3152,14 +3125,10 @@ slab_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid,
        int slab_node = numa_mem_id();
 
        flags &= gfp_allowed_mask;
-
-       lockdep_trace_alloc(flags);
-
-       if (slab_should_failslab(cachep, flags))
+       cachep = slab_pre_alloc_hook(cachep, flags);
+       if (unlikely(!cachep))
                return NULL;
 
-       cachep = memcg_kmem_get_cache(cachep, flags);
-
        cache_alloc_debugcheck_before(cachep, flags);
        local_irq_save(save_flags);
 
@@ -3188,16 +3157,11 @@ slab_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid,
   out:
        local_irq_restore(save_flags);
        ptr = cache_alloc_debugcheck_after(cachep, flags, ptr, caller);
-       kmemleak_alloc_recursive(ptr, cachep->object_size, 1, cachep->flags,
-                                flags);
 
-       if (likely(ptr)) {
-               kmemcheck_slab_alloc(cachep, flags, ptr, cachep->object_size);
-               if (unlikely(flags & __GFP_ZERO))
-                       memset(ptr, 0, cachep->object_size);
-       }
+       if (unlikely(flags & __GFP_ZERO) && ptr)
+               memset(ptr, 0, cachep->object_size);
 
-       memcg_kmem_put_cache(cachep);
+       slab_post_alloc_hook(cachep, flags, 1, &ptr);
        return ptr;
 }
 
@@ -3240,30 +3204,21 @@ slab_alloc(struct kmem_cache *cachep, gfp_t flags, unsigned long caller)
        void *objp;
 
        flags &= gfp_allowed_mask;
-
-       lockdep_trace_alloc(flags);
-
-       if (slab_should_failslab(cachep, flags))
+       cachep = slab_pre_alloc_hook(cachep, flags);
+       if (unlikely(!cachep))
                return NULL;
 
-       cachep = memcg_kmem_get_cache(cachep, flags);
-
        cache_alloc_debugcheck_before(cachep, flags);
        local_irq_save(save_flags);
        objp = __do_cache_alloc(cachep, flags);
        local_irq_restore(save_flags);
        objp = cache_alloc_debugcheck_after(cachep, flags, objp, caller);
-       kmemleak_alloc_recursive(objp, cachep->object_size, 1, cachep->flags,
-                                flags);
        prefetchw(objp);
 
-       if (likely(objp)) {
-               kmemcheck_slab_alloc(cachep, flags, objp, cachep->object_size);
-               if (unlikely(flags & __GFP_ZERO))
-                       memset(objp, 0, cachep->object_size);
-       }
+       if (unlikely(flags & __GFP_ZERO) && objp)
+               memset(objp, 0, cachep->object_size);
 
-       memcg_kmem_put_cache(cachep);
+       slab_post_alloc_hook(cachep, flags, 1, &objp);
        return objp;
 }
 
@@ -3287,7 +3242,7 @@ static void free_block(struct kmem_cache *cachep, void **objpp,
                page = virt_to_head_page(objp);
                list_del(&page->lru);
                check_spinlock_acquired_node(cachep, node);
-               slab_put_obj(cachep, page, objp, node);
+               slab_put_obj(cachep, page, objp);
                STATS_DEC_ACTIVE(cachep);
                n->free_objects++;
 
@@ -3317,9 +3272,7 @@ static void cache_flusharray(struct kmem_cache *cachep, struct array_cache *ac)
        LIST_HEAD(list);
 
        batchcount = ac->batchcount;
-#if DEBUG
-       BUG_ON(!batchcount || batchcount > ac->avail);
-#endif
+
        check_irq_off();
        n = get_node(cachep, node);
        spin_lock(&n->list_lock);
@@ -3411,16 +3364,53 @@ void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
 }
 EXPORT_SYMBOL(kmem_cache_alloc);
 
-void kmem_cache_free_bulk(struct kmem_cache *s, size_t size, void **p)
+static __always_inline void
+cache_alloc_debugcheck_after_bulk(struct kmem_cache *s, gfp_t flags,
+                                 size_t size, void **p, unsigned long caller)
 {
-       __kmem_cache_free_bulk(s, size, p);
+       size_t i;
+
+       for (i = 0; i < size; i++)
+               p[i] = cache_alloc_debugcheck_after(s, flags, p[i], caller);
 }
-EXPORT_SYMBOL(kmem_cache_free_bulk);
 
 int kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size,
-                                                               void **p)
+                         void **p)
 {
-       return __kmem_cache_alloc_bulk(s, flags, size, p);
+       size_t i;
+
+       s = slab_pre_alloc_hook(s, flags);
+       if (!s)
+               return 0;
+
+       cache_alloc_debugcheck_before(s, flags);
+
+       local_irq_disable();
+       for (i = 0; i < size; i++) {
+               void *objp = __do_cache_alloc(s, flags);
+
+               if (unlikely(!objp))
+                       goto error;
+               p[i] = objp;
+       }
+       local_irq_enable();
+
+       cache_alloc_debugcheck_after_bulk(s, flags, size, p, _RET_IP_);
+
+       /* Clear memory outside IRQ disabled section */
+       if (unlikely(flags & __GFP_ZERO))
+               for (i = 0; i < size; i++)
+                       memset(p[i], 0, s->object_size);
+
+       slab_post_alloc_hook(s, flags, size, p);
+       /* FIXME: Trace call missing. Christoph would like a bulk variant */
+       return size;
+error:
+       local_irq_enable();
+       cache_alloc_debugcheck_after_bulk(s, flags, i, p, _RET_IP_);
+       slab_post_alloc_hook(s, flags, i, p);
+       __kmem_cache_free_bulk(s, i, p);
+       return 0;
 }
 EXPORT_SYMBOL(kmem_cache_alloc_bulk);
 
@@ -3567,6 +3557,32 @@ void kmem_cache_free(struct kmem_cache *cachep, void *objp)
 }
 EXPORT_SYMBOL(kmem_cache_free);
 
+void kmem_cache_free_bulk(struct kmem_cache *orig_s, size_t size, void **p)
+{
+       struct kmem_cache *s;
+       size_t i;
+
+       local_irq_disable();
+       for (i = 0; i < size; i++) {
+               void *objp = p[i];
+
+               if (!orig_s) /* called via kfree_bulk */
+                       s = virt_to_cache(objp);
+               else
+                       s = cache_from_obj(orig_s, objp);
+
+               debug_check_no_locks_freed(objp, s->object_size);
+               if (!(s->flags & SLAB_DEBUG_OBJECTS))
+                       debug_check_no_obj_freed(objp, s->object_size);
+
+               __cache_free(s, objp, _RET_IP_);
+       }
+       local_irq_enable();
+
+       /* FIXME: add tracing */
+}
+EXPORT_SYMBOL(kmem_cache_free_bulk);
+
 /**
  * kfree - free previously allocated memory
  * @objp: pointer returned by kmalloc.