]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - mm/slab.c
[PATCH] s390: segment operation error codes
[linux-2.6-omap-h63xx.git] / mm / slab.c
index f055c14202161a7b561599536cfb269240bbd1dc..af5c5237e11a0df9d2f384383a2e8cd3b846a792 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -420,6 +420,7 @@ struct kmem_cache {
        unsigned long max_freeable;
        unsigned long node_allocs;
        unsigned long node_frees;
+       unsigned long node_overflow;
        atomic_t allochit;
        atomic_t allocmiss;
        atomic_t freehit;
@@ -465,6 +466,7 @@ struct kmem_cache {
 #define        STATS_INC_ERR(x)        ((x)->errors++)
 #define        STATS_INC_NODEALLOCS(x) ((x)->node_allocs++)
 #define        STATS_INC_NODEFREES(x)  ((x)->node_frees++)
+#define STATS_INC_ACOVERFLOW(x)   ((x)->node_overflow++)
 #define        STATS_SET_FREEABLE(x, i)                                        \
        do {                                                            \
                if ((x)->max_freeable < i)                              \
@@ -484,6 +486,7 @@ struct kmem_cache {
 #define        STATS_INC_ERR(x)        do { } while (0)
 #define        STATS_INC_NODEALLOCS(x) do { } while (0)
 #define        STATS_INC_NODEFREES(x)  do { } while (0)
+#define STATS_INC_ACOVERFLOW(x)   do { } while (0)
 #define        STATS_SET_FREEABLE(x, i) do { } while (0)
 #define STATS_INC_ALLOCHIT(x)  do { } while (0)
 #define STATS_INC_ALLOCMISS(x) do { } while (0)
@@ -1033,7 +1036,7 @@ static inline void free_alien_cache(struct array_cache **ac_ptr)
 
 #endif
 
-static int __devinit cpuup_callback(struct notifier_block *nfb,
+static int cpuup_callback(struct notifier_block *nfb,
                                    unsigned long action, void *hcpu)
 {
        long cpu = (long)hcpu;
@@ -1453,7 +1456,14 @@ static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid)
        int i;
 
        flags |= cachep->gfpflags;
+#ifndef CONFIG_MMU
+       /* nommu uses slab's for process anonymous memory allocations, so
+        * requires __GFP_COMP to properly refcount higher order allocations"
+        */
+       page = alloc_pages_node(nodeid, (flags | __GFP_COMP), cachep->gfporder);
+#else
        page = alloc_pages_node(nodeid, flags, cachep->gfporder);
+#endif
        if (!page)
                return NULL;
        addr = page_address(page);
@@ -2318,13 +2328,15 @@ EXPORT_SYMBOL(kmem_cache_destroy);
 
 /* Get the memory for a slab management obj. */
 static struct slab *alloc_slabmgmt(struct kmem_cache *cachep, void *objp,
-                                  int colour_off, gfp_t local_flags)
+                                  int colour_off, gfp_t local_flags,
+                                  int nodeid)
 {
        struct slab *slabp;
 
        if (OFF_SLAB(cachep)) {
                /* Slab management obj is off-slab. */
-               slabp = kmem_cache_alloc(cachep->slabp_cache, local_flags);
+               slabp = kmem_cache_alloc_node(cachep->slabp_cache,
+                                             local_flags, nodeid);
                if (!slabp)
                        return NULL;
        } else {
@@ -2334,6 +2346,7 @@ static struct slab *alloc_slabmgmt(struct kmem_cache *cachep, void *objp,
        slabp->inuse = 0;
        slabp->colouroff = colour_off;
        slabp->s_mem = objp + colour_off;
+       slabp->nodeid = nodeid;
        return slabp;
 }
 
@@ -2519,7 +2532,7 @@ static int cache_grow(struct kmem_cache *cachep, gfp_t flags, int nodeid)
                goto failed;
 
        /* Get slab management. */
-       slabp = alloc_slabmgmt(cachep, objp, offset, local_flags);
+       slabp = alloc_slabmgmt(cachep, objp, offset, local_flags, nodeid);
        if (!slabp)
                goto opps1;
 
@@ -3080,9 +3093,11 @@ static inline void __cache_free(struct kmem_cache *cachep, void *objp)
                        if (l3->alien && l3->alien[nodeid]) {
                                alien = l3->alien[nodeid];
                                spin_lock(&alien->lock);
-                               if (unlikely(alien->avail == alien->limit))
+                               if (unlikely(alien->avail == alien->limit)) {
+                                       STATS_INC_ACOVERFLOW(cachep);
                                        __drain_alien_cache(cachep,
                                                            alien, nodeid);
+                               }
                                alien->entry[alien->avail++] = objp;
                                spin_unlock(&alien->lock);
                        } else {
@@ -3760,7 +3775,7 @@ static void print_slabinfo_header(struct seq_file *m)
        seq_puts(m, " : slabdata <active_slabs> <num_slabs> <sharedavail>");
 #if STATS
        seq_puts(m, " : globalstat <listallocs> <maxobjs> <grown> <reaped> "
-                "<error> <maxfreeable> <nodeallocs> <remotefrees>");
+                "<error> <maxfreeable> <nodeallocs> <remotefrees> <alienoverflow>");
        seq_puts(m, " : cpustat <allochit> <allocmiss> <freehit> <freemiss>");
 #endif
        seq_putc(m, '\n');
@@ -3874,11 +3889,12 @@ static int s_show(struct seq_file *m, void *p)
                unsigned long max_freeable = cachep->max_freeable;
                unsigned long node_allocs = cachep->node_allocs;
                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", allocs, high, grown,
+                               %4lu %4lu %4lu %4lu %4lu", allocs, high, grown,
                                reaped, errors, max_freeable, node_allocs,
-                               node_frees);
+                               node_frees, overflows);
        }
        /* cpu stats */
        {