*/static bool __init debug_objects_replace_static_objects(struct kmem_cache *cache){ struct debug_bucket *db = obj_hash; struct hlist_node *tmp; struct debug_obj *obj; HLIST_HEAD(objects); int i; for (i = 0; i < ODEBUG_POOL_SIZE; i += ODEBUG_BATCH_SIZE) { if (!kmem_alloc_batch(&objects, cache, GFP_KERNEL)) goto free; pool_push_batch(&pool_global, &objects); } /* Disconnect the boot pool. */ pool_boot.first = NULL; /* Replace the active object references */ for (i = 0; i < ODEBUG_HASH_SIZE; i++, db++) { hlist_move_list(&db->list, &objects); hlist_for_each_entry(obj, &objects, node) { struct debug_obj *new = pcpu_alloc(); /* copy object data */ *new = *obj; hlist_add_head(&new->node, &db->list); } } return true;free: /* Can't use free_object_list() as the cache is not populated yet */ hlist_for_each_entry_safe(obj, tmp, &pool_global.objects, node) { hlist_del(&obj->node); kmem_cache_free(cache, obj); } return false;} /* * Called after the kmem_caches are functional to setup a dedicated * cache pool, which has the SLAB_DEBUG_OBJECTS flag set. This flag * prevents that the debug code is called on kmem_cache_free() for the * debug tracker objects to avoid recursive calls. */void __init debug_objects_mem_init(void){ struct kmem_cache *cache; int extras; if (!debug_objects_enabled) return; if (!debug_objects_selftest()) return; cache = kmem_cache_create("debug_objects_cache", sizeof (struct debug_obj), 0, SLAB_DEBUG_OBJECTS | SLAB_NOLEAKTRACE, NULL); if (!cache || !debug_objects_replace_static_objects(cache)) { debug_objects_enabled = false; pr_warn("Out of memory.\n"); return; } /* * Adjust the thresholds for allocating and freeing objects * according to the number of possible CPUs available in the * system. */ extras = num_possible_cpus() * ODEBUG_BATCH_SIZE; pool_global.max_cnt += extras; pool_global.min_cnt += extras; /* Everything worked. Expose the cache */ obj_cache = cache; static_branch_enable(&obj_cache_enabled); #ifdef CONFIG_HOTPLUG_CPU cpuhp_setup_state_nocalls(CPUHP_DEBUG_OBJ_DEAD, "object:offline", NULL, object_cpu_offline);#endif return;}Lines 1501–1585 of 1585. Previous lines
*/ static bool __init debug_objects_replace_static_objects(struct kmem_cache *cache) { struct debug_bucket *db = obj_hash; struct hlist_node *tmp; struct debug_obj *obj; HLIST_HEAD(objects); int i; for (i = 0; i < ODEBUG_POOL_SIZE; i += ODEBUG_BATCH_SIZE) { if (!kmem_alloc_batch(&objects, cache, GFP_KERNEL)) goto free; pool_push_batch(&pool_global, &objects); } /* Disconnect the boot pool. */ pool_boot.first = NULL; /* Replace the active object references */ for (i = 0; i < ODEBUG_HASH_SIZE; i++, db++) { hlist_move_list(&db->list, &objects); hlist_for_each_entry(obj, &objects, node) { struct debug_obj *new = pcpu_alloc(); /* copy object data */ *new = *obj; hlist_add_head(&new->node, &db->list); } } return true; free: /* Can't use free_object_list() as the cache is not populated yet */ hlist_for_each_entry_safe(obj, tmp, &pool_global.objects, node) { hlist_del(&obj->node); kmem_cache_free(cache, obj); } return false; } /* * Called after the kmem_caches are functional to setup a dedicated * cache pool, which has the SLAB_DEBUG_OBJECTS flag set. This flag * prevents that the debug code is called on kmem_cache_free() for the * debug tracker objects to avoid recursive calls. */ void __init debug_objects_mem_init(void) { struct kmem_cache *cache; int extras; if (!debug_objects_enabled) return; if (!debug_objects_selftest()) return; cache = kmem_cache_create("debug_objects_cache", sizeof (struct debug_obj), 0, SLAB_DEBUG_OBJECTS | SLAB_NOLEAKTRACE, NULL); if (!cache || !debug_objects_replace_static_objects(cache)) { debug_objects_enabled = false; pr_warn("Out of memory.\n"); return; } /* * Adjust the thresholds for allocating and freeing objects * according to the number of possible CPUs available in the * system. */ extras = num_possible_cpus() * ODEBUG_BATCH_SIZE; pool_global.max_cnt += extras; pool_global.min_cnt += extras; /* Everything worked. Expose the cache */ obj_cache = cache; static_branch_enable(&obj_cache_enabled); #ifdef CONFIG_HOTPLUG_CPU cpuhp_setup_state_nocalls(CPUHP_DEBUG_OBJ_DEAD, "object:offline", NULL, object_cpu_offline); #endif return; }