int i; for (i = 0; i < ODEBUG_HASH_SIZE; i++) raw_spin_lock_init(&obj_hash[i].lock); for (i = 0; i < ODEBUG_POOL_SIZE; i++) hlist_add_head(&obj_static_pool[i].node, &obj_pool);} /* * Convert the statically allocated objects to dynamic ones: */static int __init debug_objects_replace_static_objects(void){ struct debug_bucket *db = obj_hash; struct hlist_node *node, *tmp; struct debug_obj *obj, *new; HLIST_HEAD(objects); int i, cnt = 0; for (i = 0; i < ODEBUG_POOL_SIZE; i++) { obj = kmem_cache_zalloc(obj_cache, GFP_KERNEL); if (!obj) goto free; hlist_add_head(&obj->node, &objects); } /* * When debug_objects_mem_init() is called we know that only * one CPU is up, so disabling interrupts is enough * protection. This avoids the lockdep hell of lock ordering. */ local_irq_disable(); /* Remove the statically allocated objects from the pool */ hlist_for_each_entry_safe(obj, node, tmp, &obj_pool, node) hlist_del(&obj->node); /* Move the allocated objects to the pool */ hlist_move_list(&objects, &obj_pool); /* 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, node, &objects, node) { new = hlist_entry(obj_pool.first, typeof(*obj), node); hlist_del(&new->node); /* copy object data */ *new = *obj; hlist_add_head(&new->node, &db->list); cnt++; } } local_irq_enable(); printk(KERN_DEBUG "ODEBUG: %d of %d active objects replaced\n", cnt, obj_pool_used); return 0;free: hlist_for_each_entry_safe(obj, node, tmp, &objects, node) { hlist_del(&obj->node); kmem_cache_free(obj_cache, obj); } return -ENOMEM;} /* * 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){ if (!debug_objects_enabled) return; obj_cache = kmem_cache_create("debug_objects_cache", sizeof (struct debug_obj), 0, SLAB_DEBUG_OBJECTS, NULL); if (!obj_cache || debug_objects_replace_static_objects()) { debug_objects_enabled = 0; if (obj_cache) kmem_cache_destroy(obj_cache); printk(KERN_WARNING "ODEBUG: out of memory.\n"); } else debug_objects_selftest();}Lines 1001–1089 of 1089. Previous lines
int i; for (i = 0; i < ODEBUG_HASH_SIZE; i++) raw_spin_lock_init(&obj_hash[i].lock); for (i = 0; i < ODEBUG_POOL_SIZE; i++) hlist_add_head(&obj_static_pool[i].node, &obj_pool); } /* * Convert the statically allocated objects to dynamic ones: */ static int __init debug_objects_replace_static_objects(void) { struct debug_bucket *db = obj_hash; struct hlist_node *node, *tmp; struct debug_obj *obj, *new; HLIST_HEAD(objects); int i, cnt = 0; for (i = 0; i < ODEBUG_POOL_SIZE; i++) { obj = kmem_cache_zalloc(obj_cache, GFP_KERNEL); if (!obj) goto free; hlist_add_head(&obj->node, &objects); } /* * When debug_objects_mem_init() is called we know that only * one CPU is up, so disabling interrupts is enough * protection. This avoids the lockdep hell of lock ordering. */ local_irq_disable(); /* Remove the statically allocated objects from the pool */ hlist_for_each_entry_safe(obj, node, tmp, &obj_pool, node) hlist_del(&obj->node); /* Move the allocated objects to the pool */ hlist_move_list(&objects, &obj_pool); /* 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, node, &objects, node) { new = hlist_entry(obj_pool.first, typeof(*obj), node); hlist_del(&new->node); /* copy object data */ *new = *obj; hlist_add_head(&new->node, &db->list); cnt++; } } local_irq_enable(); printk(KERN_DEBUG "ODEBUG: %d of %d active objects replaced\n", cnt, obj_pool_used); return 0; free: hlist_for_each_entry_safe(obj, node, tmp, &objects, node) { hlist_del(&obj->node); kmem_cache_free(obj_cache, obj); } return -ENOMEM; } /* * 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) { if (!debug_objects_enabled) return; obj_cache = kmem_cache_create("debug_objects_cache", sizeof (struct debug_obj), 0, SLAB_DEBUG_OBJECTS, NULL); if (!obj_cache || debug_objects_replace_static_objects()) { debug_objects_enabled = 0; if (obj_cache) kmem_cache_destroy(obj_cache); printk(KERN_WARNING "ODEBUG: out of memory.\n"); } else debug_objects_selftest(); }