[PATCH] reiserfs: add missing D-cache flushing
[safe/jmp/linux-2.6] / mm / slab.c
index 9f34b49..86f5d6e 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
 #include       <linux/module.h>
 #include       <linux/rcupdate.h>
 #include       <linux/string.h>
+#include       <linux/uaccess.h>
 #include       <linux/nodemask.h>
 #include       <linux/mempolicy.h>
 #include       <linux/mutex.h>
 #include       <linux/rtmutex.h>
 
-#include       <asm/uaccess.h>
 #include       <asm/cacheflush.h>
 #include       <asm/tlbflush.h>
 #include       <asm/page.h>
@@ -1605,12 +1605,7 @@ static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid)
        flags |= __GFP_COMP;
 #endif
 
-       /*
-        * Under NUMA we want memory on the indicated node. We will handle
-        * the needed fallback ourselves since we want to serve from our
-        * per node object lists first for other nodes.
-        */
-       flags |= cachep->gfpflags | GFP_THISNODE;
+       flags |= cachep->gfpflags;
 
        page = alloc_pages_node(nodeid, flags, cachep->gfporder);
        if (!page)
@@ -2129,7 +2124,6 @@ kmem_cache_create (const char *name, size_t size, size_t align,
        mutex_lock(&cache_chain_mutex);
 
        list_for_each_entry(pc, &cache_chain, next) {
-               mm_segment_t old_fs = get_fs();
                char tmp;
                int res;
 
@@ -2138,9 +2132,7 @@ kmem_cache_create (const char *name, size_t size, size_t align,
                 * destroy its slab cache and no-one else reuses the vmalloc
                 * area of the module.  Print a warning.
                 */
-               set_fs(KERNEL_DS);
-               res = __get_user(tmp, pc->name);
-               set_fs(old_fs);
+               res = probe_kernel_address(pc->name, tmp);
                if (res) {
                        printk("SLAB: cache with size %d has lost its name\n",
                               pc->buffer_size);
@@ -2237,7 +2229,7 @@ kmem_cache_create (const char *name, size_t size, size_t align,
        align = ralign;
 
        /* Get cache's description obj. */
-       cachep = kmem_cache_zalloc(&cache_cache, SLAB_KERNEL);
+       cachep = kmem_cache_zalloc(&cache_cache, GFP_KERNEL);
        if (!cachep)
                goto oops;
 
@@ -2567,7 +2559,7 @@ static struct slab *alloc_slabmgmt(struct kmem_cache *cachep, void *objp,
        if (OFF_SLAB(cachep)) {
                /* Slab management obj is off-slab. */
                slabp = kmem_cache_alloc_node(cachep->slabp_cache,
-                                             local_flags, nodeid);
+                                             local_flags & ~GFP_THISNODE, nodeid);
                if (!slabp)
                        return NULL;
        } else {
@@ -2637,7 +2629,7 @@ static void cache_init_objs(struct kmem_cache *cachep,
 
 static void kmem_flagcheck(struct kmem_cache *cachep, gfp_t flags)
 {
-       if (flags & SLAB_DMA)
+       if (flags & GFP_DMA)
                BUG_ON(!(cachep->gfpflags & GFP_DMA));
        else
                BUG_ON(cachep->gfpflags & GFP_DMA);
@@ -2708,10 +2700,10 @@ static void slab_map_pages(struct kmem_cache *cache, struct slab *slab,
  * Grow (by 1) the number of slabs within a cache.  This is called by
  * kmem_cache_alloc() when there are no active objs left in a cache.
  */
-static int cache_grow(struct kmem_cache *cachep, gfp_t flags, int nodeid)
+static int cache_grow(struct kmem_cache *cachep,
+               gfp_t flags, int nodeid, void *objp)
 {
        struct slab *slabp;
-       void *objp;
        size_t offset;
        gfp_t local_flags;
        unsigned long ctor_flags;
@@ -2721,7 +2713,7 @@ static int cache_grow(struct kmem_cache *cachep, gfp_t flags, int nodeid)
         * Be lazy and only check for valid flags here,  keeping it out of the
         * critical path in kmem_cache_alloc().
         */
-       BUG_ON(flags & ~(SLAB_DMA | GFP_LEVEL_MASK | __GFP_NO_GROW));
+       BUG_ON(flags & ~(GFP_DMA | GFP_LEVEL_MASK | __GFP_NO_GROW));
        if (flags & __GFP_NO_GROW)
                return 0;
 
@@ -2763,12 +2755,14 @@ static int cache_grow(struct kmem_cache *cachep, gfp_t flags, int nodeid)
         * Get mem for the objs.  Attempt to allocate a physical page from
         * 'nodeid'.
         */
-       objp = kmem_getpages(cachep, flags, nodeid);
+       if (!objp)
+               objp = kmem_getpages(cachep, flags, nodeid);
        if (!objp)
                goto failed;
 
        /* Get slab management. */
-       slabp = alloc_slabmgmt(cachep, objp, offset, local_flags, nodeid);
+       slabp = alloc_slabmgmt(cachep, objp, offset,
+                       local_flags & ~GFP_THISNODE, nodeid);
        if (!slabp)
                goto opps1;
 
@@ -3006,7 +3000,7 @@ alloc_done:
 
        if (unlikely(!ac->avail)) {
                int x;
-               x = cache_grow(cachep, flags, node);
+               x = cache_grow(cachep, flags | GFP_THISNODE, node, NULL);
 
                /* cache_grow can reenable interrupts, then ac could change. */
                ac = cpu_cache_get(cachep);
@@ -3166,9 +3160,11 @@ static void *alternate_node_alloc(struct kmem_cache *cachep, gfp_t flags)
 
 /*
  * Fallback function if there was no memory available and no objects on a
- * certain node and we are allowed to fall back. We mimick the behavior of
- * the page allocator. We fall back according to a zonelist determined by
- * the policy layer while obeying cpuset constraints.
+ * certain node and fall back is permitted. First we scan all the
+ * available nodelists for available objects. If that fails then we
+ * perform an allocation without specifying a node. This allows the page
+ * allocator to do its reclaim / fallback magic. We then insert the
+ * slab into the proper nodelist and then allocate from it.
  */
 void *fallback_alloc(struct kmem_cache *cache, gfp_t flags)
 {
@@ -3176,15 +3172,51 @@ void *fallback_alloc(struct kmem_cache *cache, gfp_t flags)
                                        ->node_zonelists[gfp_zone(flags)];
        struct zone **z;
        void *obj = NULL;
+       int nid;
 
+retry:
+       /*
+        * Look through allowed nodes for objects available
+        * from existing per node queues.
+        */
        for (z = zonelist->zones; *z && !obj; z++) {
-               int nid = zone_to_nid(*z);
+               nid = zone_to_nid(*z);
 
-               if (zone_idx(*z) <= ZONE_NORMAL &&
-                               cpuset_zone_allowed(*z, flags) &&
-                               cache->nodelists[nid])
-                       obj = ____cache_alloc_node(cache,
-                                       flags | __GFP_THISNODE, nid);
+               if (cpuset_zone_allowed(*z, flags) &&
+                       cache->nodelists[nid] &&
+                       cache->nodelists[nid]->free_objects)
+                               obj = ____cache_alloc_node(cache,
+                                       flags | GFP_THISNODE, nid);
+       }
+
+       if (!obj) {
+               /*
+                * This allocation will be performed within the constraints
+                * of the current cpuset / memory policy requirements.
+                * We may trigger various forms of reclaim on the allowed
+                * set and go into memory reserves if necessary.
+                */
+               obj = kmem_getpages(cache, flags, -1);
+               if (obj) {
+                       /*
+                        * Insert into the appropriate per node queues
+                        */
+                       nid = page_to_nid(virt_to_page(obj));
+                       if (cache_grow(cache, flags, nid, obj)) {
+                               obj = ____cache_alloc_node(cache,
+                                       flags | GFP_THISNODE, nid);
+                               if (!obj)
+                                       /*
+                                        * Another processor may allocate the
+                                        * objects in the slab since we are
+                                        * not holding any locks.
+                                        */
+                                       goto retry;
+                       } else {
+                               kmem_freepages(cache, obj);
+                               obj = NULL;
+                       }
+               }
        }
        return obj;
 }
@@ -3241,7 +3273,7 @@ retry:
 
 must_grow:
        spin_unlock(&l3->list_lock);
-       x = cache_grow(cachep, flags, nodeid);
+       x = cache_grow(cachep, flags | GFP_THISNODE, nodeid, NULL);
        if (x)
                goto retry;
 
@@ -3459,29 +3491,45 @@ out:
  * @flags: See kmalloc().
  * @nodeid: node number of the target node.
  *
- * Identical to kmem_cache_alloc, except that this function is slow
- * and can sleep. And it will allocate memory on the given node, which
- * can improve the performance for cpu bound structures.
- * New and improved: it will now make sure that the object gets
- * put on the correct node list so that there is no false sharing.
+ * Identical to kmem_cache_alloc but it will allocate memory on the given
+ * node, which can improve the performance for cpu bound structures.
+ *
+ * Fallback to other node is possible if __GFP_THISNODE is not set.
  */
 static __always_inline void *
 __cache_alloc_node(struct kmem_cache *cachep, gfp_t flags,
                int nodeid, void *caller)
 {
        unsigned long save_flags;
-       void *ptr;
+       void *ptr = NULL;
 
        cache_alloc_debugcheck_before(cachep, flags);
        local_irq_save(save_flags);
 
-       if (nodeid == -1 || nodeid == numa_node_id() ||
-                       !cachep->nodelists[nodeid])
-               ptr = ____cache_alloc(cachep, flags);
-       else
-               ptr = ____cache_alloc_node(cachep, flags, nodeid);
-       local_irq_restore(save_flags);
+       if (unlikely(nodeid == -1))
+               nodeid = numa_node_id();
 
+       if (likely(cachep->nodelists[nodeid])) {
+               if (nodeid == numa_node_id()) {
+                       /*
+                        * Use the locally cached objects if possible.
+                        * However ____cache_alloc does not allow fallback
+                        * to other nodes. It may fail while we still have
+                        * objects on other nodes available.
+                        */
+                       ptr = ____cache_alloc(cachep, flags);
+               }
+               if (!ptr) {
+                       /* ___cache_alloc_node can fall back to other nodes */
+                       ptr = ____cache_alloc_node(cachep, flags, nodeid);
+               }
+       } else {
+               /* Node not bootstrapped yet */
+               if (!(flags & __GFP_THISNODE))
+                       ptr = fallback_alloc(cachep, flags);
+       }
+
+       local_irq_restore(save_flags);
        ptr = cache_alloc_debugcheck_after(cachep, flags, ptr, caller);
 
        return ptr;