ARM: 8985/1: efi/decompressor: deal with HYP mode boot gracefully
[linux-2.6-microblaze.git] / mm / slub.c
index b762450..b8f798b 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -679,6 +679,20 @@ static void slab_fix(struct kmem_cache *s, char *fmt, ...)
        va_end(args);
 }
 
+static bool freelist_corrupted(struct kmem_cache *s, struct page *page,
+                              void *freelist, void *nextfree)
+{
+       if ((s->flags & SLAB_CONSISTENCY_CHECKS) &&
+           !check_valid_pointer(s, page, nextfree)) {
+               object_err(s, page, freelist, "Freechain corrupt");
+               freelist = NULL;
+               slab_fix(s, "Isolate corrupted freechain");
+               return true;
+       }
+
+       return false;
+}
+
 static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p)
 {
        unsigned int off;       /* Offset of last byte */
@@ -1410,6 +1424,11 @@ static inline void inc_slabs_node(struct kmem_cache *s, int node,
 static inline void dec_slabs_node(struct kmem_cache *s, int node,
                                                        int objects) {}
 
+static bool freelist_corrupted(struct kmem_cache *s, struct page *page,
+                              void *freelist, void *nextfree)
+{
+       return false;
+}
 #endif /* CONFIG_SLUB_DEBUG */
 
 /*
@@ -1919,7 +1938,7 @@ static void *get_any_partial(struct kmem_cache *s, gfp_t flags,
        struct zonelist *zonelist;
        struct zoneref *z;
        struct zone *zone;
-       enum zone_type high_zoneidx = gfp_zone(flags);
+       enum zone_type highest_zoneidx = gfp_zone(flags);
        void *object;
        unsigned int cpuset_mems_cookie;
 
@@ -1948,7 +1967,7 @@ static void *get_any_partial(struct kmem_cache *s, gfp_t flags,
        do {
                cpuset_mems_cookie = read_mems_allowed_begin();
                zonelist = node_zonelist(mempolicy_slab_node(), flags);
-               for_each_zone_zonelist(zone, z, zonelist, high_zoneidx) {
+               for_each_zone_zonelist(zone, z, zonelist, highest_zoneidx) {
                        struct kmem_cache_node *n;
 
                        n = get_node(s, zone_to_nid(zone));
@@ -1994,7 +2013,7 @@ static void *get_partial(struct kmem_cache *s, gfp_t flags, int node,
 
 #ifdef CONFIG_PREEMPTION
 /*
- * Calculate the next globally unique transaction for disambiguiation
+ * Calculate the next globally unique transaction for disambiguation
  * during cmpxchg. The transactions start with the cpu number and are then
  * incremented by CONFIG_NR_CPUS.
  */
@@ -2093,6 +2112,14 @@ static void deactivate_slab(struct kmem_cache *s, struct page *page,
                void *prior;
                unsigned long counters;
 
+               /*
+                * If 'nextfree' is invalid, it is possible that the object at
+                * 'freelist' is already corrupted.  So isolate all objects
+                * starting at 'freelist'.
+                */
+               if (freelist_corrupted(s, page, freelist, nextfree))
+                       break;
+
                do {
                        prior = page->freelist;
                        counters = page->counters;
@@ -3739,12 +3766,14 @@ error:
 }
 
 static void list_slab_objects(struct kmem_cache *s, struct page *page,
-                                                       const char *text)
+                             const char *text, unsigned long *map)
 {
 #ifdef CONFIG_SLUB_DEBUG
        void *addr = page_address(page);
        void *p;
-       unsigned long *map;
+
+       if (!map)
+               return;
 
        slab_err(s, page, text, s->name);
        slab_lock(page);
@@ -3757,8 +3786,6 @@ static void list_slab_objects(struct kmem_cache *s, struct page *page,
                        print_tracking(s, p);
                }
        }
-       put_map(map);
-
        slab_unlock(page);
 #endif
 }
@@ -3772,6 +3799,11 @@ static void free_partial(struct kmem_cache *s, struct kmem_cache_node *n)
 {
        LIST_HEAD(discard);
        struct page *page, *h;
+       unsigned long *map = NULL;
+
+#ifdef CONFIG_SLUB_DEBUG
+       map = bitmap_alloc(oo_objects(s->max), GFP_KERNEL);
+#endif
 
        BUG_ON(irqs_disabled());
        spin_lock_irq(&n->list_lock);
@@ -3781,11 +3813,16 @@ static void free_partial(struct kmem_cache *s, struct kmem_cache_node *n)
                        list_add(&page->slab_list, &discard);
                } else {
                        list_slab_objects(s, page,
-                       "Objects remaining in %s on __kmem_cache_shutdown()");
+                         "Objects remaining in %s on __kmem_cache_shutdown()",
+                         map);
                }
        }
        spin_unlock_irq(&n->list_lock);
 
+#ifdef CONFIG_SLUB_DEBUG
+       bitmap_free(map);
+#endif
+
        list_for_each_entry_safe(page, h, &discard, slab_list)
                discard_slab(s, page);
 }
@@ -4408,6 +4445,7 @@ void *__kmalloc_track_caller(size_t size, gfp_t gfpflags, unsigned long caller)
 
        return ret;
 }
+EXPORT_SYMBOL(__kmalloc_track_caller);
 
 #ifdef CONFIG_NUMA
 void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags,
@@ -4438,6 +4476,7 @@ void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags,
 
        return ret;
 }
+EXPORT_SYMBOL(__kmalloc_node_track_caller);
 #endif
 
 #ifdef CONFIG_SYSFS
@@ -5654,7 +5693,8 @@ static void memcg_propagate_slab_attrs(struct kmem_cache *s)
                 */
                if (buffer)
                        buf = buffer;
-               else if (root_cache->max_attr_size < ARRAY_SIZE(mbuf))
+               else if (root_cache->max_attr_size < ARRAY_SIZE(mbuf) &&
+                        !IS_ENABLED(CONFIG_SLUB_STATS))
                        buf = mbuf;
                else {
                        buffer = (char *) get_zeroed_page(GFP_KERNEL);
@@ -5688,19 +5728,6 @@ static struct kobj_type slab_ktype = {
        .release = kmem_cache_release,
 };
 
-static int uevent_filter(struct kset *kset, struct kobject *kobj)
-{
-       struct kobj_type *ktype = get_ktype(kobj);
-
-       if (ktype == &slab_ktype)
-               return 1;
-       return 0;
-}
-
-static const struct kset_uevent_ops slab_uevent_ops = {
-       .filter = uevent_filter,
-};
-
 static struct kset *slab_kset;
 
 static inline struct kset *cache_kset(struct kmem_cache *s)
@@ -5768,7 +5795,6 @@ static void sysfs_slab_remove_workfn(struct work_struct *work)
 #ifdef CONFIG_MEMCG
        kset_unregister(s->memcg_kset);
 #endif
-       kobject_uevent(&s->kobj, KOBJ_REMOVE);
 out:
        kobject_put(&s->kobj);
 }
@@ -5809,8 +5835,10 @@ static int sysfs_slab_add(struct kmem_cache *s)
 
        s->kobj.kset = kset;
        err = kobject_init_and_add(&s->kobj, &slab_ktype, NULL, "%s", name);
-       if (err)
+       if (err) {
+               kobject_put(&s->kobj);
                goto out;
+       }
 
        err = sysfs_create_group(&s->kobj, &slab_attr_group);
        if (err)
@@ -5826,7 +5854,6 @@ static int sysfs_slab_add(struct kmem_cache *s)
        }
 #endif
 
-       kobject_uevent(&s->kobj, KOBJ_ADD);
        if (!unmergeable) {
                /* Setup first alias */
                sysfs_slab_alias(s, s->name);
@@ -5907,7 +5934,7 @@ static int __init slab_sysfs_init(void)
 
        mutex_lock(&slab_mutex);
 
-       slab_kset = kset_create_and_add("slab", &slab_uevent_ops, kernel_kobj);
+       slab_kset = kset_create_and_add("slab", NULL, kernel_kobj);
        if (!slab_kset) {
                mutex_unlock(&slab_mutex);
                pr_err("Cannot register slab subsystem.\n");