sched: Prevent balance_push() on remote runqueues
[linux-2.6-microblaze.git] / lib / debugobjects.c
index fe45579..9e14ae0 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/slab.h>
 #include <linux/hash.h>
 #include <linux/kmemleak.h>
+#include <linux/cpu.h>
 
 #define ODEBUG_HASH_BITS       14
 #define ODEBUG_HASH_SIZE       (1 << ODEBUG_HASH_BITS)
@@ -90,7 +91,7 @@ static int                    debug_objects_pool_size __read_mostly
                                = ODEBUG_POOL_SIZE;
 static int                     debug_objects_pool_min_level __read_mostly
                                = ODEBUG_POOL_MIN_LEVEL;
-static struct debug_obj_descr  *descr_test  __read_mostly;
+static const struct debug_obj_descr *descr_test  __read_mostly;
 static struct kmem_cache       *obj_cache __read_mostly;
 
 /*
@@ -223,7 +224,7 @@ static struct debug_obj *__alloc_object(struct hlist_head *list)
  * Must be called with interrupts disabled.
  */
 static struct debug_obj *
-alloc_object(void *addr, struct debug_bucket *b, struct debug_obj_descr *descr)
+alloc_object(void *addr, struct debug_bucket *b, const struct debug_obj_descr *descr)
 {
        struct debug_percpu_free *percpu_pool = this_cpu_ptr(&percpu_obj_pool);
        struct debug_obj *obj;
@@ -433,6 +434,25 @@ static void free_object(struct debug_obj *obj)
        }
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+static int object_cpu_offline(unsigned int cpu)
+{
+       struct debug_percpu_free *percpu_pool;
+       struct hlist_node *tmp;
+       struct debug_obj *obj;
+
+       /* Remote access is safe as the CPU is dead already */
+       percpu_pool = per_cpu_ptr(&percpu_obj_pool, cpu);
+       hlist_for_each_entry_safe(obj, tmp, &percpu_pool->free_objs, node) {
+               hlist_del(&obj->node);
+               kmem_cache_free(obj_cache, obj);
+       }
+       percpu_pool->obj_free = 0;
+
+       return 0;
+}
+#endif
+
 /*
  * We run out of memory. That means we probably have tons of objects
  * allocated.
@@ -475,7 +495,7 @@ static struct debug_bucket *get_bucket(unsigned long addr)
 
 static void debug_print_object(struct debug_obj *obj, char *msg)
 {
-       struct debug_obj_descr *descr = obj->descr;
+       const struct debug_obj_descr *descr = obj->descr;
        static int limit;
 
        if (limit < 5 && descr != descr_test) {
@@ -529,7 +549,7 @@ static void debug_object_is_on_stack(void *addr, int onstack)
 }
 
 static void
-__debug_object_init(void *addr, struct debug_obj_descr *descr, int onstack)
+__debug_object_init(void *addr, const struct debug_obj_descr *descr, int onstack)
 {
        enum debug_obj_state state;
        bool check_stack = false;
@@ -587,7 +607,7 @@ __debug_object_init(void *addr, struct debug_obj_descr *descr, int onstack)
  * @addr:      address of the object
  * @descr:     pointer to an object specific debug description structure
  */
-void debug_object_init(void *addr, struct debug_obj_descr *descr)
+void debug_object_init(void *addr, const struct debug_obj_descr *descr)
 {
        if (!debug_objects_enabled)
                return;
@@ -602,7 +622,7 @@ EXPORT_SYMBOL_GPL(debug_object_init);
  * @addr:      address of the object
  * @descr:     pointer to an object specific debug description structure
  */
-void debug_object_init_on_stack(void *addr, struct debug_obj_descr *descr)
+void debug_object_init_on_stack(void *addr, const struct debug_obj_descr *descr)
 {
        if (!debug_objects_enabled)
                return;
@@ -617,7 +637,7 @@ EXPORT_SYMBOL_GPL(debug_object_init_on_stack);
  * @descr:     pointer to an object specific debug description structure
  * Returns 0 for success, -EINVAL for check failed.
  */
-int debug_object_activate(void *addr, struct debug_obj_descr *descr)
+int debug_object_activate(void *addr, const struct debug_obj_descr *descr)
 {
        enum debug_obj_state state;
        struct debug_bucket *db;
@@ -695,7 +715,7 @@ EXPORT_SYMBOL_GPL(debug_object_activate);
  * @addr:      address of the object
  * @descr:     pointer to an object specific debug description structure
  */
-void debug_object_deactivate(void *addr, struct debug_obj_descr *descr)
+void debug_object_deactivate(void *addr, const struct debug_obj_descr *descr)
 {
        struct debug_bucket *db;
        struct debug_obj *obj;
@@ -747,7 +767,7 @@ EXPORT_SYMBOL_GPL(debug_object_deactivate);
  * @addr:      address of the object
  * @descr:     pointer to an object specific debug description structure
  */
-void debug_object_destroy(void *addr, struct debug_obj_descr *descr)
+void debug_object_destroy(void *addr, const struct debug_obj_descr *descr)
 {
        enum debug_obj_state state;
        struct debug_bucket *db;
@@ -797,7 +817,7 @@ EXPORT_SYMBOL_GPL(debug_object_destroy);
  * @addr:      address of the object
  * @descr:     pointer to an object specific debug description structure
  */
-void debug_object_free(void *addr, struct debug_obj_descr *descr)
+void debug_object_free(void *addr, const struct debug_obj_descr *descr)
 {
        enum debug_obj_state state;
        struct debug_bucket *db;
@@ -838,7 +858,7 @@ EXPORT_SYMBOL_GPL(debug_object_free);
  * @addr:      address of the object
  * @descr:     pointer to an object specific debug description structure
  */
-void debug_object_assert_init(void *addr, struct debug_obj_descr *descr)
+void debug_object_assert_init(void *addr, const struct debug_obj_descr *descr)
 {
        struct debug_bucket *db;
        struct debug_obj *obj;
@@ -886,7 +906,7 @@ EXPORT_SYMBOL_GPL(debug_object_assert_init);
  * @next:      state to move to if expected state is found
  */
 void
-debug_object_active_state(void *addr, struct debug_obj_descr *descr,
+debug_object_active_state(void *addr, const struct debug_obj_descr *descr,
                          unsigned int expect, unsigned int next)
 {
        struct debug_bucket *db;
@@ -934,7 +954,7 @@ EXPORT_SYMBOL_GPL(debug_object_active_state);
 static void __debug_check_no_obj_freed(const void *address, unsigned long size)
 {
        unsigned long flags, oaddr, saddr, eaddr, paddr, chunks;
-       struct debug_obj_descr *descr;
+       const struct debug_obj_descr *descr;
        enum debug_obj_state state;
        struct debug_bucket *db;
        struct hlist_node *tmp;
@@ -1052,7 +1072,7 @@ struct self_test {
        unsigned long   dummy2[3];
 };
 
-static __initdata struct debug_obj_descr descr_type_test;
+static __initconst const struct debug_obj_descr descr_type_test;
 
 static bool __init is_static_object(void *addr)
 {
@@ -1177,7 +1197,7 @@ out:
        return res;
 }
 
-static __initdata struct debug_obj_descr descr_type_test = {
+static __initconst const struct debug_obj_descr descr_type_test = {
        .name                   = "selftest",
        .is_static_object       = is_static_object,
        .fixup_init             = fixup_init,
@@ -1367,6 +1387,11 @@ void __init debug_objects_mem_init(void)
        } else
                debug_objects_selftest();
 
+#ifdef CONFIG_HOTPLUG_CPU
+       cpuhp_setup_state_nocalls(CPUHP_DEBUG_OBJ_DEAD, "object:offline", NULL,
+                                       object_cpu_offline);
+#endif
+
        /*
         * Increase the thresholds for allocating and freeing objects
         * according to the number of possible CPUs available in the system.