mm: compaction: memory compaction core
[safe/jmp/linux-2.6] / mm / slab.c
index 3230cd2..02786e1 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
 #define        BYTES_PER_WORD          sizeof(void *)
 #define        REDZONE_ALIGN           max(BYTES_PER_WORD, __alignof__(unsigned long long))
 
-#ifndef ARCH_KMALLOC_MINALIGN
-/*
- * Enforce a minimum alignment for the kmalloc caches.
- * Usually, the kmalloc caches are cache_line_size() aligned, except when
- * DEBUG and FORCED_DEBUG are enabled, then they are BYTES_PER_WORD aligned.
- * Some archs want to perform DMA into kmalloc caches and need a guaranteed
- * alignment larger than the alignment of a 64-bit integer.
- * ARCH_KMALLOC_MINALIGN allows that.
- * Note that increasing this value may disable some debug features.
- */
-#define ARCH_KMALLOC_MINALIGN __alignof__(unsigned long long)
-#endif
-
-#ifndef ARCH_SLAB_MINALIGN
-/*
- * Enforce a minimum alignment for all caches.
- * Intended for archs that get misalignment faults even for BYTES_PER_WORD
- * aligned buffers. Includes ARCH_KMALLOC_MINALIGN.
- * If possible: Do not enable this flag for CONFIG_DEBUG_SLAB, it disables
- * some debug features.
- */
-#define ARCH_SLAB_MINALIGN 0
-#endif
-
 #ifndef ARCH_KMALLOC_FLAGS
 #define ARCH_KMALLOC_FLAGS SLAB_HWCACHE_ALIGN
 #endif
@@ -2313,8 +2289,8 @@ kmem_cache_create (const char *name, size_t size, size_t align,
        if (ralign < align) {
                ralign = align;
        }
-       /* disable debug if necessary */
-       if (ralign > __alignof__(unsigned long long))
+       /* disable debug if not aligning with REDZONE_ALIGN */
+       if (ralign & (__alignof__(unsigned long long) - 1))
                flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER);
        /*
         * 4) Store it.
@@ -2340,8 +2316,8 @@ kmem_cache_create (const char *name, size_t size, size_t align,
         */
        if (flags & SLAB_RED_ZONE) {
                /* add space for red zone words */
-               cachep->obj_offset += sizeof(unsigned long long);
-               size += 2 * sizeof(unsigned long long);
+               cachep->obj_offset += align;
+               size += align + sizeof(unsigned long long);
        }
        if (flags & SLAB_STORE_USER) {
                /* user store requires one word storage behind the end of
@@ -3241,10 +3217,12 @@ static void *alternate_node_alloc(struct kmem_cache *cachep, gfp_t flags)
        if (in_interrupt() || (flags & __GFP_THISNODE))
                return NULL;
        nid_alloc = nid_here = numa_node_id();
+       get_mems_allowed();
        if (cpuset_do_slab_mem_spread() && (cachep->flags & SLAB_MEM_SPREAD))
                nid_alloc = cpuset_mem_spread_node();
        else if (current->mempolicy)
                nid_alloc = slab_node(current->mempolicy);
+       put_mems_allowed();
        if (nid_alloc != nid_here)
                return ____cache_alloc_node(cachep, flags, nid_alloc);
        return NULL;
@@ -3271,6 +3249,7 @@ static void *fallback_alloc(struct kmem_cache *cache, gfp_t flags)
        if (flags & __GFP_THISNODE)
                return NULL;
 
+       get_mems_allowed();
        zonelist = node_zonelist(slab_node(current->mempolicy), flags);
        local_flags = flags & (GFP_CONSTRAINT_MASK|GFP_RECLAIM_MASK);
 
@@ -3326,6 +3305,7 @@ retry:
                        }
                }
        }
+       put_mems_allowed();
        return obj;
 }
 
@@ -3695,21 +3675,10 @@ EXPORT_SYMBOL(kmem_cache_alloc_notrace);
  */
 int kmem_ptr_validate(struct kmem_cache *cachep, const void *ptr)
 {
-       unsigned long addr = (unsigned long)ptr;
-       unsigned long min_addr = PAGE_OFFSET;
-       unsigned long align_mask = BYTES_PER_WORD - 1;
        unsigned long size = cachep->buffer_size;
        struct page *page;
 
-       if (unlikely(addr < min_addr))
-               goto out;
-       if (unlikely(addr > (unsigned long)high_memory - size))
-               goto out;
-       if (unlikely(addr & align_mask))
-               goto out;
-       if (unlikely(!kern_addr_valid(addr)))
-               goto out;
-       if (unlikely(!kern_addr_valid(addr + size - 1)))
+       if (unlikely(!kern_ptr_validate(ptr, size)))
                goto out;
        page = virt_to_page(ptr);
        if (unlikely(!PageSlab(page)))
@@ -4320,10 +4289,11 @@ static int s_show(struct seq_file *m, void *p)
                unsigned long node_frees = cachep->node_frees;
                unsigned long overflows = cachep->node_overflow;
 
-               seq_printf(m, " : globalstat %7lu %6lu %5lu %4lu \
-                               %4lu %4lu %4lu %4lu %4lu", allocs, high, grown,
-                               reaped, errors, max_freeable, node_allocs,
-                               node_frees, overflows);
+               seq_printf(m, " : globalstat %7lu %6lu %5lu %4lu "
+                          "%4lu %4lu %4lu %4lu %4lu",
+                          allocs, high, grown,
+                          reaped, errors, max_freeable, node_allocs,
+                          node_frees, overflows);
        }
        /* cpu stats */
        {