diff options
Diffstat (limited to 'lib/debugobjects.c')
-rw-r--r-- | lib/debugobjects.c | 75 |
1 files changed, 38 insertions, 37 deletions
diff --git a/lib/debugobjects.c b/lib/debugobjects.c index eae56fddfa3..b862b30369f 100644 --- a/lib/debugobjects.c +++ b/lib/debugobjects.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/sched.h> | 12 | #include <linux/sched.h> |
13 | #include <linux/seq_file.h> | 13 | #include <linux/seq_file.h> |
14 | #include <linux/debugfs.h> | 14 | #include <linux/debugfs.h> |
15 | #include <linux/slab.h> | ||
15 | #include <linux/hash.h> | 16 | #include <linux/hash.h> |
16 | 17 | ||
17 | #define ODEBUG_HASH_BITS 14 | 18 | #define ODEBUG_HASH_BITS 14 |
@@ -26,14 +27,14 @@ | |||
26 | 27 | ||
27 | struct debug_bucket { | 28 | struct debug_bucket { |
28 | struct hlist_head list; | 29 | struct hlist_head list; |
29 | spinlock_t lock; | 30 | raw_spinlock_t lock; |
30 | }; | 31 | }; |
31 | 32 | ||
32 | static struct debug_bucket obj_hash[ODEBUG_HASH_SIZE]; | 33 | static struct debug_bucket obj_hash[ODEBUG_HASH_SIZE]; |
33 | 34 | ||
34 | static struct debug_obj obj_static_pool[ODEBUG_POOL_SIZE] __initdata; | 35 | static struct debug_obj obj_static_pool[ODEBUG_POOL_SIZE] __initdata; |
35 | 36 | ||
36 | static DEFINE_SPINLOCK(pool_lock); | 37 | static DEFINE_RAW_SPINLOCK(pool_lock); |
37 | 38 | ||
38 | static HLIST_HEAD(obj_pool); | 39 | static HLIST_HEAD(obj_pool); |
39 | 40 | ||
@@ -96,10 +97,10 @@ static int fill_pool(void) | |||
96 | if (!new) | 97 | if (!new) |
97 | return obj_pool_free; | 98 | return obj_pool_free; |
98 | 99 | ||
99 | spin_lock_irqsave(&pool_lock, flags); | 100 | raw_spin_lock_irqsave(&pool_lock, flags); |
100 | hlist_add_head(&new->node, &obj_pool); | 101 | hlist_add_head(&new->node, &obj_pool); |
101 | obj_pool_free++; | 102 | obj_pool_free++; |
102 | spin_unlock_irqrestore(&pool_lock, flags); | 103 | raw_spin_unlock_irqrestore(&pool_lock, flags); |
103 | } | 104 | } |
104 | return obj_pool_free; | 105 | return obj_pool_free; |
105 | } | 106 | } |
@@ -133,7 +134,7 @@ alloc_object(void *addr, struct debug_bucket *b, struct debug_obj_descr *descr) | |||
133 | { | 134 | { |
134 | struct debug_obj *obj = NULL; | 135 | struct debug_obj *obj = NULL; |
135 | 136 | ||
136 | spin_lock(&pool_lock); | 137 | raw_spin_lock(&pool_lock); |
137 | if (obj_pool.first) { | 138 | if (obj_pool.first) { |
138 | obj = hlist_entry(obj_pool.first, typeof(*obj), node); | 139 | obj = hlist_entry(obj_pool.first, typeof(*obj), node); |
139 | 140 | ||
@@ -152,7 +153,7 @@ alloc_object(void *addr, struct debug_bucket *b, struct debug_obj_descr *descr) | |||
152 | if (obj_pool_free < obj_pool_min_free) | 153 | if (obj_pool_free < obj_pool_min_free) |
153 | obj_pool_min_free = obj_pool_free; | 154 | obj_pool_min_free = obj_pool_free; |
154 | } | 155 | } |
155 | spin_unlock(&pool_lock); | 156 | raw_spin_unlock(&pool_lock); |
156 | 157 | ||
157 | return obj; | 158 | return obj; |
158 | } | 159 | } |
@@ -165,7 +166,7 @@ static void free_obj_work(struct work_struct *work) | |||
165 | struct debug_obj *obj; | 166 | struct debug_obj *obj; |
166 | unsigned long flags; | 167 | unsigned long flags; |
167 | 168 | ||
168 | spin_lock_irqsave(&pool_lock, flags); | 169 | raw_spin_lock_irqsave(&pool_lock, flags); |
169 | while (obj_pool_free > ODEBUG_POOL_SIZE) { | 170 | while (obj_pool_free > ODEBUG_POOL_SIZE) { |
170 | obj = hlist_entry(obj_pool.first, typeof(*obj), node); | 171 | obj = hlist_entry(obj_pool.first, typeof(*obj), node); |
171 | hlist_del(&obj->node); | 172 | hlist_del(&obj->node); |
@@ -174,11 +175,11 @@ static void free_obj_work(struct work_struct *work) | |||
174 | * We release pool_lock across kmem_cache_free() to | 175 | * We release pool_lock across kmem_cache_free() to |
175 | * avoid contention on pool_lock. | 176 | * avoid contention on pool_lock. |
176 | */ | 177 | */ |
177 | spin_unlock_irqrestore(&pool_lock, flags); | 178 | raw_spin_unlock_irqrestore(&pool_lock, flags); |
178 | kmem_cache_free(obj_cache, obj); | 179 | kmem_cache_free(obj_cache, obj); |
179 | spin_lock_irqsave(&pool_lock, flags); | 180 | raw_spin_lock_irqsave(&pool_lock, flags); |
180 | } | 181 | } |
181 | spin_unlock_irqrestore(&pool_lock, flags); | 182 | raw_spin_unlock_irqrestore(&pool_lock, flags); |
182 | } | 183 | } |
183 | 184 | ||
184 | /* | 185 | /* |
@@ -190,7 +191,7 @@ static void free_object(struct debug_obj *obj) | |||
190 | unsigned long flags; | 191 | unsigned long flags; |
191 | int sched = 0; | 192 | int sched = 0; |
192 | 193 | ||
193 | spin_lock_irqsave(&pool_lock, flags); | 194 | raw_spin_lock_irqsave(&pool_lock, flags); |
194 | /* | 195 | /* |
195 | * schedule work when the pool is filled and the cache is | 196 | * schedule work when the pool is filled and the cache is |
196 | * initialized: | 197 | * initialized: |
@@ -200,7 +201,7 @@ static void free_object(struct debug_obj *obj) | |||
200 | hlist_add_head(&obj->node, &obj_pool); | 201 | hlist_add_head(&obj->node, &obj_pool); |
201 | obj_pool_free++; | 202 | obj_pool_free++; |
202 | obj_pool_used--; | 203 | obj_pool_used--; |
203 | spin_unlock_irqrestore(&pool_lock, flags); | 204 | raw_spin_unlock_irqrestore(&pool_lock, flags); |
204 | if (sched) | 205 | if (sched) |
205 | schedule_work(&debug_obj_work); | 206 | schedule_work(&debug_obj_work); |
206 | } | 207 | } |
@@ -221,9 +222,9 @@ static void debug_objects_oom(void) | |||
221 | printk(KERN_WARNING "ODEBUG: Out of memory. ODEBUG disabled\n"); | 222 | printk(KERN_WARNING "ODEBUG: Out of memory. ODEBUG disabled\n"); |
222 | 223 | ||
223 | for (i = 0; i < ODEBUG_HASH_SIZE; i++, db++) { | 224 | for (i = 0; i < ODEBUG_HASH_SIZE; i++, db++) { |
224 | spin_lock_irqsave(&db->lock, flags); | 225 | raw_spin_lock_irqsave(&db->lock, flags); |
225 | hlist_move_list(&db->list, &freelist); | 226 | hlist_move_list(&db->list, &freelist); |
226 | spin_unlock_irqrestore(&db->lock, flags); | 227 | raw_spin_unlock_irqrestore(&db->lock, flags); |
227 | 228 | ||
228 | /* Now free them */ | 229 | /* Now free them */ |
229 | hlist_for_each_entry_safe(obj, node, tmp, &freelist, node) { | 230 | hlist_for_each_entry_safe(obj, node, tmp, &freelist, node) { |
@@ -303,14 +304,14 @@ __debug_object_init(void *addr, struct debug_obj_descr *descr, int onstack) | |||
303 | 304 | ||
304 | db = get_bucket((unsigned long) addr); | 305 | db = get_bucket((unsigned long) addr); |
305 | 306 | ||
306 | spin_lock_irqsave(&db->lock, flags); | 307 | raw_spin_lock_irqsave(&db->lock, flags); |
307 | 308 | ||
308 | obj = lookup_object(addr, db); | 309 | obj = lookup_object(addr, db); |
309 | if (!obj) { | 310 | if (!obj) { |
310 | obj = alloc_object(addr, db, descr); | 311 | obj = alloc_object(addr, db, descr); |
311 | if (!obj) { | 312 | if (!obj) { |
312 | debug_objects_enabled = 0; | 313 | debug_objects_enabled = 0; |
313 | spin_unlock_irqrestore(&db->lock, flags); | 314 | raw_spin_unlock_irqrestore(&db->lock, flags); |
314 | debug_objects_oom(); | 315 | debug_objects_oom(); |
315 | return; | 316 | return; |
316 | } | 317 | } |
@@ -327,7 +328,7 @@ __debug_object_init(void *addr, struct debug_obj_descr *descr, int onstack) | |||
327 | case ODEBUG_STATE_ACTIVE: | 328 | case ODEBUG_STATE_ACTIVE: |
328 | debug_print_object(obj, "init"); | 329 | debug_print_object(obj, "init"); |
329 | state = obj->state; | 330 | state = obj->state; |
330 | spin_unlock_irqrestore(&db->lock, flags); | 331 | raw_spin_unlock_irqrestore(&db->lock, flags); |
331 | debug_object_fixup(descr->fixup_init, addr, state); | 332 | debug_object_fixup(descr->fixup_init, addr, state); |
332 | return; | 333 | return; |
333 | 334 | ||
@@ -338,7 +339,7 @@ __debug_object_init(void *addr, struct debug_obj_descr *descr, int onstack) | |||
338 | break; | 339 | break; |
339 | } | 340 | } |
340 | 341 | ||
341 | spin_unlock_irqrestore(&db->lock, flags); | 342 | raw_spin_unlock_irqrestore(&db->lock, flags); |
342 | } | 343 | } |
343 | 344 | ||
344 | /** | 345 | /** |
@@ -385,7 +386,7 @@ void debug_object_activate(void *addr, struct debug_obj_descr *descr) | |||
385 | 386 | ||
386 | db = get_bucket((unsigned long) addr); | 387 | db = get_bucket((unsigned long) addr); |
387 | 388 | ||
388 | spin_lock_irqsave(&db->lock, flags); | 389 | raw_spin_lock_irqsave(&db->lock, flags); |
389 | 390 | ||
390 | obj = lookup_object(addr, db); | 391 | obj = lookup_object(addr, db); |
391 | if (obj) { | 392 | if (obj) { |
@@ -398,7 +399,7 @@ void debug_object_activate(void *addr, struct debug_obj_descr *descr) | |||
398 | case ODEBUG_STATE_ACTIVE: | 399 | case ODEBUG_STATE_ACTIVE: |
399 | debug_print_object(obj, "activate"); | 400 | debug_print_object(obj, "activate"); |
400 | state = obj->state; | 401 | state = obj->state; |
401 | spin_unlock_irqrestore(&db->lock, flags); | 402 | raw_spin_unlock_irqrestore(&db->lock, flags); |
402 | debug_object_fixup(descr->fixup_activate, addr, state); | 403 | debug_object_fixup(descr->fixup_activate, addr, state); |
403 | return; | 404 | return; |
404 | 405 | ||
@@ -408,11 +409,11 @@ void debug_object_activate(void *addr, struct debug_obj_descr *descr) | |||
408 | default: | 409 | default: |
409 | break; | 410 | break; |
410 | } | 411 | } |
411 | spin_unlock_irqrestore(&db->lock, flags); | 412 | raw_spin_unlock_irqrestore(&db->lock, flags); |
412 | return; | 413 | return; |
413 | } | 414 | } |
414 | 415 | ||
415 | spin_unlock_irqrestore(&db->lock, flags); | 416 | raw_spin_unlock_irqrestore(&db->lock, flags); |
416 | /* | 417 | /* |
417 | * This happens when a static object is activated. We | 418 | * This happens when a static object is activated. We |
418 | * let the type specific code decide whether this is | 419 | * let the type specific code decide whether this is |
@@ -438,7 +439,7 @@ void debug_object_deactivate(void *addr, struct debug_obj_descr *descr) | |||
438 | 439 | ||
439 | db = get_bucket((unsigned long) addr); | 440 | db = get_bucket((unsigned long) addr); |
440 | 441 | ||
441 | spin_lock_irqsave(&db->lock, flags); | 442 | raw_spin_lock_irqsave(&db->lock, flags); |
442 | 443 | ||
443 | obj = lookup_object(addr, db); | 444 | obj = lookup_object(addr, db); |
444 | if (obj) { | 445 | if (obj) { |
@@ -463,7 +464,7 @@ void debug_object_deactivate(void *addr, struct debug_obj_descr *descr) | |||
463 | debug_print_object(&o, "deactivate"); | 464 | debug_print_object(&o, "deactivate"); |
464 | } | 465 | } |
465 | 466 | ||
466 | spin_unlock_irqrestore(&db->lock, flags); | 467 | raw_spin_unlock_irqrestore(&db->lock, flags); |
467 | } | 468 | } |
468 | 469 | ||
469 | /** | 470 | /** |
@@ -483,7 +484,7 @@ void debug_object_destroy(void *addr, struct debug_obj_descr *descr) | |||
483 | 484 | ||
484 | db = get_bucket((unsigned long) addr); | 485 | db = get_bucket((unsigned long) addr); |
485 | 486 | ||
486 | spin_lock_irqsave(&db->lock, flags); | 487 | raw_spin_lock_irqsave(&db->lock, flags); |
487 | 488 | ||
488 | obj = lookup_object(addr, db); | 489 | obj = lookup_object(addr, db); |
489 | if (!obj) | 490 | if (!obj) |
@@ -498,7 +499,7 @@ void debug_object_destroy(void *addr, struct debug_obj_descr *descr) | |||
498 | case ODEBUG_STATE_ACTIVE: | 499 | case ODEBUG_STATE_ACTIVE: |
499 | debug_print_object(obj, "destroy"); | 500 | debug_print_object(obj, "destroy"); |
500 | state = obj->state; | 501 | state = obj->state; |
501 | spin_unlock_irqrestore(&db->lock, flags); | 502 | raw_spin_unlock_irqrestore(&db->lock, flags); |
502 | debug_object_fixup(descr->fixup_destroy, addr, state); | 503 | debug_object_fixup(descr->fixup_destroy, addr, state); |
503 | return; | 504 | return; |
504 | 505 | ||
@@ -509,7 +510,7 @@ void debug_object_destroy(void *addr, struct debug_obj_descr *descr) | |||
509 | break; | 510 | break; |
510 | } | 511 | } |
511 | out_unlock: | 512 | out_unlock: |
512 | spin_unlock_irqrestore(&db->lock, flags); | 513 | raw_spin_unlock_irqrestore(&db->lock, flags); |
513 | } | 514 | } |
514 | 515 | ||
515 | /** | 516 | /** |
@@ -529,7 +530,7 @@ void debug_object_free(void *addr, struct debug_obj_descr *descr) | |||
529 | 530 | ||
530 | db = get_bucket((unsigned long) addr); | 531 | db = get_bucket((unsigned long) addr); |
531 | 532 | ||
532 | spin_lock_irqsave(&db->lock, flags); | 533 | raw_spin_lock_irqsave(&db->lock, flags); |
533 | 534 | ||
534 | obj = lookup_object(addr, db); | 535 | obj = lookup_object(addr, db); |
535 | if (!obj) | 536 | if (!obj) |
@@ -539,17 +540,17 @@ void debug_object_free(void *addr, struct debug_obj_descr *descr) | |||
539 | case ODEBUG_STATE_ACTIVE: | 540 | case ODEBUG_STATE_ACTIVE: |
540 | debug_print_object(obj, "free"); | 541 | debug_print_object(obj, "free"); |
541 | state = obj->state; | 542 | state = obj->state; |
542 | spin_unlock_irqrestore(&db->lock, flags); | 543 | raw_spin_unlock_irqrestore(&db->lock, flags); |
543 | debug_object_fixup(descr->fixup_free, addr, state); | 544 | debug_object_fixup(descr->fixup_free, addr, state); |
544 | return; | 545 | return; |
545 | default: | 546 | default: |
546 | hlist_del(&obj->node); | 547 | hlist_del(&obj->node); |
547 | spin_unlock_irqrestore(&db->lock, flags); | 548 | raw_spin_unlock_irqrestore(&db->lock, flags); |
548 | free_object(obj); | 549 | free_object(obj); |
549 | return; | 550 | return; |
550 | } | 551 | } |
551 | out_unlock: | 552 | out_unlock: |
552 | spin_unlock_irqrestore(&db->lock, flags); | 553 | raw_spin_unlock_irqrestore(&db->lock, flags); |
553 | } | 554 | } |
554 | 555 | ||
555 | #ifdef CONFIG_DEBUG_OBJECTS_FREE | 556 | #ifdef CONFIG_DEBUG_OBJECTS_FREE |
@@ -575,7 +576,7 @@ static void __debug_check_no_obj_freed(const void *address, unsigned long size) | |||
575 | 576 | ||
576 | repeat: | 577 | repeat: |
577 | cnt = 0; | 578 | cnt = 0; |
578 | spin_lock_irqsave(&db->lock, flags); | 579 | raw_spin_lock_irqsave(&db->lock, flags); |
579 | hlist_for_each_entry_safe(obj, node, tmp, &db->list, node) { | 580 | hlist_for_each_entry_safe(obj, node, tmp, &db->list, node) { |
580 | cnt++; | 581 | cnt++; |
581 | oaddr = (unsigned long) obj->object; | 582 | oaddr = (unsigned long) obj->object; |
@@ -587,7 +588,7 @@ repeat: | |||
587 | debug_print_object(obj, "free"); | 588 | debug_print_object(obj, "free"); |
588 | descr = obj->descr; | 589 | descr = obj->descr; |
589 | state = obj->state; | 590 | state = obj->state; |
590 | spin_unlock_irqrestore(&db->lock, flags); | 591 | raw_spin_unlock_irqrestore(&db->lock, flags); |
591 | debug_object_fixup(descr->fixup_free, | 592 | debug_object_fixup(descr->fixup_free, |
592 | (void *) oaddr, state); | 593 | (void *) oaddr, state); |
593 | goto repeat; | 594 | goto repeat; |
@@ -597,7 +598,7 @@ repeat: | |||
597 | break; | 598 | break; |
598 | } | 599 | } |
599 | } | 600 | } |
600 | spin_unlock_irqrestore(&db->lock, flags); | 601 | raw_spin_unlock_irqrestore(&db->lock, flags); |
601 | 602 | ||
602 | /* Now free them */ | 603 | /* Now free them */ |
603 | hlist_for_each_entry_safe(obj, node, tmp, &freelist, node) { | 604 | hlist_for_each_entry_safe(obj, node, tmp, &freelist, node) { |
@@ -783,7 +784,7 @@ check_results(void *addr, enum debug_obj_state state, int fixups, int warnings) | |||
783 | 784 | ||
784 | db = get_bucket((unsigned long) addr); | 785 | db = get_bucket((unsigned long) addr); |
785 | 786 | ||
786 | spin_lock_irqsave(&db->lock, flags); | 787 | raw_spin_lock_irqsave(&db->lock, flags); |
787 | 788 | ||
788 | obj = lookup_object(addr, db); | 789 | obj = lookup_object(addr, db); |
789 | if (!obj && state != ODEBUG_STATE_NONE) { | 790 | if (!obj && state != ODEBUG_STATE_NONE) { |
@@ -807,7 +808,7 @@ check_results(void *addr, enum debug_obj_state state, int fixups, int warnings) | |||
807 | } | 808 | } |
808 | res = 0; | 809 | res = 0; |
809 | out: | 810 | out: |
810 | spin_unlock_irqrestore(&db->lock, flags); | 811 | raw_spin_unlock_irqrestore(&db->lock, flags); |
811 | if (res) | 812 | if (res) |
812 | debug_objects_enabled = 0; | 813 | debug_objects_enabled = 0; |
813 | return res; | 814 | return res; |
@@ -907,7 +908,7 @@ void __init debug_objects_early_init(void) | |||
907 | int i; | 908 | int i; |
908 | 909 | ||
909 | for (i = 0; i < ODEBUG_HASH_SIZE; i++) | 910 | for (i = 0; i < ODEBUG_HASH_SIZE; i++) |
910 | spin_lock_init(&obj_hash[i].lock); | 911 | raw_spin_lock_init(&obj_hash[i].lock); |
911 | 912 | ||
912 | for (i = 0; i < ODEBUG_POOL_SIZE; i++) | 913 | for (i = 0; i < ODEBUG_POOL_SIZE; i++) |
913 | hlist_add_head(&obj_static_pool[i].node, &obj_pool); | 914 | hlist_add_head(&obj_static_pool[i].node, &obj_pool); |