diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-06 10:53:34 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-06 10:53:34 -0500 |
commit | 8c717b72dec32a50666175b62b41de24e4b39be7 (patch) | |
tree | e2b4335496cbddb5cded7b1bfd7579ee33f60505 | |
parent | 07d106d0a33d6063d2061305903deb02489eba20 (diff) | |
parent | dc4218bd0fe499fce2896f88101ea42dac1f60fc (diff) |
Merge branch 'core-debugobjects-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
* 'core-debugobjects-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
timer: Use debugobjects to catch deletion of uninitialized timers
timer: Setup uninitialized timer with a stub callback
debugobjects: Extend to assert that an object is initialized
debugobjects: Be smarter about static objects
-rw-r--r-- | Documentation/DocBook/debugobjects.tmpl | 50 | ||||
-rw-r--r-- | include/linux/debugobjects.h | 6 | ||||
-rw-r--r-- | kernel/timer.c | 62 | ||||
-rw-r--r-- | lib/debugobjects.c | 54 |
4 files changed, 162 insertions, 10 deletions
diff --git a/Documentation/DocBook/debugobjects.tmpl b/Documentation/DocBook/debugobjects.tmpl index 08ff908aa7a2..24979f691e3e 100644 --- a/Documentation/DocBook/debugobjects.tmpl +++ b/Documentation/DocBook/debugobjects.tmpl | |||
@@ -96,6 +96,7 @@ | |||
96 | <listitem><para>debug_object_deactivate</para></listitem> | 96 | <listitem><para>debug_object_deactivate</para></listitem> |
97 | <listitem><para>debug_object_destroy</para></listitem> | 97 | <listitem><para>debug_object_destroy</para></listitem> |
98 | <listitem><para>debug_object_free</para></listitem> | 98 | <listitem><para>debug_object_free</para></listitem> |
99 | <listitem><para>debug_object_assert_init</para></listitem> | ||
99 | </itemizedlist> | 100 | </itemizedlist> |
100 | Each of these functions takes the address of the real object and | 101 | Each of these functions takes the address of the real object and |
101 | a pointer to the object type specific debug description | 102 | a pointer to the object type specific debug description |
@@ -273,6 +274,26 @@ | |||
273 | debug checks. | 274 | debug checks. |
274 | </para> | 275 | </para> |
275 | </sect1> | 276 | </sect1> |
277 | |||
278 | <sect1 id="debug_object_assert_init"> | ||
279 | <title>debug_object_assert_init</title> | ||
280 | <para> | ||
281 | This function is called to assert that an object has been | ||
282 | initialized. | ||
283 | </para> | ||
284 | <para> | ||
285 | When the real object is not tracked by debugobjects, it calls | ||
286 | fixup_assert_init of the object type description structure | ||
287 | provided by the caller, with the hardcoded object state | ||
288 | ODEBUG_NOT_AVAILABLE. The fixup function can correct the problem | ||
289 | by calling debug_object_init and other specific initializing | ||
290 | functions. | ||
291 | </para> | ||
292 | <para> | ||
293 | When the real object is already tracked by debugobjects it is | ||
294 | ignored. | ||
295 | </para> | ||
296 | </sect1> | ||
276 | </chapter> | 297 | </chapter> |
277 | <chapter id="fixupfunctions"> | 298 | <chapter id="fixupfunctions"> |
278 | <title>Fixup functions</title> | 299 | <title>Fixup functions</title> |
@@ -381,6 +402,35 @@ | |||
381 | statistics. | 402 | statistics. |
382 | </para> | 403 | </para> |
383 | </sect1> | 404 | </sect1> |
405 | <sect1 id="fixup_assert_init"> | ||
406 | <title>fixup_assert_init</title> | ||
407 | <para> | ||
408 | This function is called from the debug code whenever a problem | ||
409 | in debug_object_assert_init is detected. | ||
410 | </para> | ||
411 | <para> | ||
412 | Called from debug_object_assert_init() with a hardcoded state | ||
413 | ODEBUG_STATE_NOTAVAILABLE when the object is not found in the | ||
414 | debug bucket. | ||
415 | </para> | ||
416 | <para> | ||
417 | The function returns 1 when the fixup was successful, | ||
418 | otherwise 0. The return value is used to update the | ||
419 | statistics. | ||
420 | </para> | ||
421 | <para> | ||
422 | Note, this function should make sure debug_object_init() is | ||
423 | called before returning. | ||
424 | </para> | ||
425 | <para> | ||
426 | The handling of statically initialized objects is a special | ||
427 | case. The fixup function should check if this is a legitimate | ||
428 | case of a statically initialized object or not. In this case only | ||
429 | debug_object_init() should be called to make the object known to | ||
430 | the tracker. Then the function should return 0 because this is not | ||
431 | a real fixup. | ||
432 | </para> | ||
433 | </sect1> | ||
384 | </chapter> | 434 | </chapter> |
385 | <chapter id="bugs"> | 435 | <chapter id="bugs"> |
386 | <title>Known Bugs And Assumptions</title> | 436 | <title>Known Bugs And Assumptions</title> |
diff --git a/include/linux/debugobjects.h b/include/linux/debugobjects.h index 65970b811e22..0e5f5785d9f2 100644 --- a/include/linux/debugobjects.h +++ b/include/linux/debugobjects.h | |||
@@ -46,6 +46,8 @@ struct debug_obj { | |||
46 | * fails | 46 | * fails |
47 | * @fixup_free: fixup function, which is called when the free check | 47 | * @fixup_free: fixup function, which is called when the free check |
48 | * fails | 48 | * fails |
49 | * @fixup_assert_init: fixup function, which is called when the assert_init | ||
50 | * check fails | ||
49 | */ | 51 | */ |
50 | struct debug_obj_descr { | 52 | struct debug_obj_descr { |
51 | const char *name; | 53 | const char *name; |
@@ -54,6 +56,7 @@ struct debug_obj_descr { | |||
54 | int (*fixup_activate) (void *addr, enum debug_obj_state state); | 56 | int (*fixup_activate) (void *addr, enum debug_obj_state state); |
55 | int (*fixup_destroy) (void *addr, enum debug_obj_state state); | 57 | int (*fixup_destroy) (void *addr, enum debug_obj_state state); |
56 | int (*fixup_free) (void *addr, enum debug_obj_state state); | 58 | int (*fixup_free) (void *addr, enum debug_obj_state state); |
59 | int (*fixup_assert_init)(void *addr, enum debug_obj_state state); | ||
57 | }; | 60 | }; |
58 | 61 | ||
59 | #ifdef CONFIG_DEBUG_OBJECTS | 62 | #ifdef CONFIG_DEBUG_OBJECTS |
@@ -64,6 +67,7 @@ extern void debug_object_activate (void *addr, struct debug_obj_descr *descr); | |||
64 | extern void debug_object_deactivate(void *addr, struct debug_obj_descr *descr); | 67 | extern void debug_object_deactivate(void *addr, struct debug_obj_descr *descr); |
65 | extern void debug_object_destroy (void *addr, struct debug_obj_descr *descr); | 68 | extern void debug_object_destroy (void *addr, struct debug_obj_descr *descr); |
66 | extern void debug_object_free (void *addr, struct debug_obj_descr *descr); | 69 | extern void debug_object_free (void *addr, struct debug_obj_descr *descr); |
70 | extern void debug_object_assert_init(void *addr, struct debug_obj_descr *descr); | ||
67 | 71 | ||
68 | /* | 72 | /* |
69 | * Active state: | 73 | * Active state: |
@@ -89,6 +93,8 @@ static inline void | |||
89 | debug_object_destroy (void *addr, struct debug_obj_descr *descr) { } | 93 | debug_object_destroy (void *addr, struct debug_obj_descr *descr) { } |
90 | static inline void | 94 | static inline void |
91 | debug_object_free (void *addr, struct debug_obj_descr *descr) { } | 95 | debug_object_free (void *addr, struct debug_obj_descr *descr) { } |
96 | static inline void | ||
97 | debug_object_assert_init(void *addr, struct debug_obj_descr *descr) { } | ||
92 | 98 | ||
93 | static inline void debug_objects_early_init(void) { } | 99 | static inline void debug_objects_early_init(void) { } |
94 | static inline void debug_objects_mem_init(void) { } | 100 | static inline void debug_objects_mem_init(void) { } |
diff --git a/kernel/timer.c b/kernel/timer.c index 9c3c62b0c4bc..a297ffcf888e 100644 --- a/kernel/timer.c +++ b/kernel/timer.c | |||
@@ -427,6 +427,12 @@ static int timer_fixup_init(void *addr, enum debug_obj_state state) | |||
427 | } | 427 | } |
428 | } | 428 | } |
429 | 429 | ||
430 | /* Stub timer callback for improperly used timers. */ | ||
431 | static void stub_timer(unsigned long data) | ||
432 | { | ||
433 | WARN_ON(1); | ||
434 | } | ||
435 | |||
430 | /* | 436 | /* |
431 | * fixup_activate is called when: | 437 | * fixup_activate is called when: |
432 | * - an active object is activated | 438 | * - an active object is activated |
@@ -450,7 +456,8 @@ static int timer_fixup_activate(void *addr, enum debug_obj_state state) | |||
450 | debug_object_activate(timer, &timer_debug_descr); | 456 | debug_object_activate(timer, &timer_debug_descr); |
451 | return 0; | 457 | return 0; |
452 | } else { | 458 | } else { |
453 | WARN_ON_ONCE(1); | 459 | setup_timer(timer, stub_timer, 0); |
460 | return 1; | ||
454 | } | 461 | } |
455 | return 0; | 462 | return 0; |
456 | 463 | ||
@@ -480,12 +487,40 @@ static int timer_fixup_free(void *addr, enum debug_obj_state state) | |||
480 | } | 487 | } |
481 | } | 488 | } |
482 | 489 | ||
490 | /* | ||
491 | * fixup_assert_init is called when: | ||
492 | * - an untracked/uninit-ed object is found | ||
493 | */ | ||
494 | static int timer_fixup_assert_init(void *addr, enum debug_obj_state state) | ||
495 | { | ||
496 | struct timer_list *timer = addr; | ||
497 | |||
498 | switch (state) { | ||
499 | case ODEBUG_STATE_NOTAVAILABLE: | ||
500 | if (timer->entry.prev == TIMER_ENTRY_STATIC) { | ||
501 | /* | ||
502 | * This is not really a fixup. The timer was | ||
503 | * statically initialized. We just make sure that it | ||
504 | * is tracked in the object tracker. | ||
505 | */ | ||
506 | debug_object_init(timer, &timer_debug_descr); | ||
507 | return 0; | ||
508 | } else { | ||
509 | setup_timer(timer, stub_timer, 0); | ||
510 | return 1; | ||
511 | } | ||
512 | default: | ||
513 | return 0; | ||
514 | } | ||
515 | } | ||
516 | |||
483 | static struct debug_obj_descr timer_debug_descr = { | 517 | static struct debug_obj_descr timer_debug_descr = { |
484 | .name = "timer_list", | 518 | .name = "timer_list", |
485 | .debug_hint = timer_debug_hint, | 519 | .debug_hint = timer_debug_hint, |
486 | .fixup_init = timer_fixup_init, | 520 | .fixup_init = timer_fixup_init, |
487 | .fixup_activate = timer_fixup_activate, | 521 | .fixup_activate = timer_fixup_activate, |
488 | .fixup_free = timer_fixup_free, | 522 | .fixup_free = timer_fixup_free, |
523 | .fixup_assert_init = timer_fixup_assert_init, | ||
489 | }; | 524 | }; |
490 | 525 | ||
491 | static inline void debug_timer_init(struct timer_list *timer) | 526 | static inline void debug_timer_init(struct timer_list *timer) |
@@ -508,6 +543,11 @@ static inline void debug_timer_free(struct timer_list *timer) | |||
508 | debug_object_free(timer, &timer_debug_descr); | 543 | debug_object_free(timer, &timer_debug_descr); |
509 | } | 544 | } |
510 | 545 | ||
546 | static inline void debug_timer_assert_init(struct timer_list *timer) | ||
547 | { | ||
548 | debug_object_assert_init(timer, &timer_debug_descr); | ||
549 | } | ||
550 | |||
511 | static void __init_timer(struct timer_list *timer, | 551 | static void __init_timer(struct timer_list *timer, |
512 | const char *name, | 552 | const char *name, |
513 | struct lock_class_key *key); | 553 | struct lock_class_key *key); |
@@ -531,6 +571,7 @@ EXPORT_SYMBOL_GPL(destroy_timer_on_stack); | |||
531 | static inline void debug_timer_init(struct timer_list *timer) { } | 571 | static inline void debug_timer_init(struct timer_list *timer) { } |
532 | static inline void debug_timer_activate(struct timer_list *timer) { } | 572 | static inline void debug_timer_activate(struct timer_list *timer) { } |
533 | static inline void debug_timer_deactivate(struct timer_list *timer) { } | 573 | static inline void debug_timer_deactivate(struct timer_list *timer) { } |
574 | static inline void debug_timer_assert_init(struct timer_list *timer) { } | ||
534 | #endif | 575 | #endif |
535 | 576 | ||
536 | static inline void debug_init(struct timer_list *timer) | 577 | static inline void debug_init(struct timer_list *timer) |
@@ -552,6 +593,11 @@ static inline void debug_deactivate(struct timer_list *timer) | |||
552 | trace_timer_cancel(timer); | 593 | trace_timer_cancel(timer); |
553 | } | 594 | } |
554 | 595 | ||
596 | static inline void debug_assert_init(struct timer_list *timer) | ||
597 | { | ||
598 | debug_timer_assert_init(timer); | ||
599 | } | ||
600 | |||
555 | static void __init_timer(struct timer_list *timer, | 601 | static void __init_timer(struct timer_list *timer, |
556 | const char *name, | 602 | const char *name, |
557 | struct lock_class_key *key) | 603 | struct lock_class_key *key) |
@@ -902,6 +948,8 @@ int del_timer(struct timer_list *timer) | |||
902 | unsigned long flags; | 948 | unsigned long flags; |
903 | int ret = 0; | 949 | int ret = 0; |
904 | 950 | ||
951 | debug_assert_init(timer); | ||
952 | |||
905 | timer_stats_timer_clear_start_info(timer); | 953 | timer_stats_timer_clear_start_info(timer); |
906 | if (timer_pending(timer)) { | 954 | if (timer_pending(timer)) { |
907 | base = lock_timer_base(timer, &flags); | 955 | base = lock_timer_base(timer, &flags); |
@@ -932,6 +980,8 @@ int try_to_del_timer_sync(struct timer_list *timer) | |||
932 | unsigned long flags; | 980 | unsigned long flags; |
933 | int ret = -1; | 981 | int ret = -1; |
934 | 982 | ||
983 | debug_assert_init(timer); | ||
984 | |||
935 | base = lock_timer_base(timer, &flags); | 985 | base = lock_timer_base(timer, &flags); |
936 | 986 | ||
937 | if (base->running_timer == timer) | 987 | if (base->running_timer == timer) |
diff --git a/lib/debugobjects.c b/lib/debugobjects.c index a78b7c6e042c..77cb245f8e7b 100644 --- a/lib/debugobjects.c +++ b/lib/debugobjects.c | |||
@@ -268,12 +268,16 @@ static void debug_print_object(struct debug_obj *obj, char *msg) | |||
268 | * Try to repair the damage, so we have a better chance to get useful | 268 | * Try to repair the damage, so we have a better chance to get useful |
269 | * debug output. | 269 | * debug output. |
270 | */ | 270 | */ |
271 | static void | 271 | static int |
272 | debug_object_fixup(int (*fixup)(void *addr, enum debug_obj_state state), | 272 | debug_object_fixup(int (*fixup)(void *addr, enum debug_obj_state state), |
273 | void * addr, enum debug_obj_state state) | 273 | void * addr, enum debug_obj_state state) |
274 | { | 274 | { |
275 | int fixed = 0; | ||
276 | |||
275 | if (fixup) | 277 | if (fixup) |
276 | debug_objects_fixups += fixup(addr, state); | 278 | fixed = fixup(addr, state); |
279 | debug_objects_fixups += fixed; | ||
280 | return fixed; | ||
277 | } | 281 | } |
278 | 282 | ||
279 | static void debug_object_is_on_stack(void *addr, int onstack) | 283 | static void debug_object_is_on_stack(void *addr, int onstack) |
@@ -386,6 +390,9 @@ void debug_object_activate(void *addr, struct debug_obj_descr *descr) | |||
386 | struct debug_bucket *db; | 390 | struct debug_bucket *db; |
387 | struct debug_obj *obj; | 391 | struct debug_obj *obj; |
388 | unsigned long flags; | 392 | unsigned long flags; |
393 | struct debug_obj o = { .object = addr, | ||
394 | .state = ODEBUG_STATE_NOTAVAILABLE, | ||
395 | .descr = descr }; | ||
389 | 396 | ||
390 | if (!debug_objects_enabled) | 397 | if (!debug_objects_enabled) |
391 | return; | 398 | return; |
@@ -425,8 +432,9 @@ void debug_object_activate(void *addr, struct debug_obj_descr *descr) | |||
425 | * let the type specific code decide whether this is | 432 | * let the type specific code decide whether this is |
426 | * true or not. | 433 | * true or not. |
427 | */ | 434 | */ |
428 | debug_object_fixup(descr->fixup_activate, addr, | 435 | if (debug_object_fixup(descr->fixup_activate, addr, |
429 | ODEBUG_STATE_NOTAVAILABLE); | 436 | ODEBUG_STATE_NOTAVAILABLE)) |
437 | debug_print_object(&o, "activate"); | ||
430 | } | 438 | } |
431 | 439 | ||
432 | /** | 440 | /** |
@@ -563,6 +571,44 @@ out_unlock: | |||
563 | } | 571 | } |
564 | 572 | ||
565 | /** | 573 | /** |
574 | * debug_object_assert_init - debug checks when object should be init-ed | ||
575 | * @addr: address of the object | ||
576 | * @descr: pointer to an object specific debug description structure | ||
577 | */ | ||
578 | void debug_object_assert_init(void *addr, struct debug_obj_descr *descr) | ||
579 | { | ||
580 | struct debug_bucket *db; | ||
581 | struct debug_obj *obj; | ||
582 | unsigned long flags; | ||
583 | |||
584 | if (!debug_objects_enabled) | ||
585 | return; | ||
586 | |||
587 | db = get_bucket((unsigned long) addr); | ||
588 | |||
589 | raw_spin_lock_irqsave(&db->lock, flags); | ||
590 | |||
591 | obj = lookup_object(addr, db); | ||
592 | if (!obj) { | ||
593 | struct debug_obj o = { .object = addr, | ||
594 | .state = ODEBUG_STATE_NOTAVAILABLE, | ||
595 | .descr = descr }; | ||
596 | |||
597 | raw_spin_unlock_irqrestore(&db->lock, flags); | ||
598 | /* | ||
599 | * Maybe the object is static. Let the type specific | ||
600 | * code decide what to do. | ||
601 | */ | ||
602 | if (debug_object_fixup(descr->fixup_assert_init, addr, | ||
603 | ODEBUG_STATE_NOTAVAILABLE)) | ||
604 | debug_print_object(&o, "assert_init"); | ||
605 | return; | ||
606 | } | ||
607 | |||
608 | raw_spin_unlock_irqrestore(&db->lock, flags); | ||
609 | } | ||
610 | |||
611 | /** | ||
566 | * debug_object_active_state - debug checks object usage state machine | 612 | * debug_object_active_state - debug checks object usage state machine |
567 | * @addr: address of the object | 613 | * @addr: address of the object |
568 | * @descr: pointer to an object specific debug description structure | 614 | * @descr: pointer to an object specific debug description structure |