summaryrefslogtreecommitdiffstats
path: root/lib/kobject.c
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2013-06-27 10:06:14 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-07-25 18:39:04 -0400
commitc817a67ecba7c3c2aaa104796d78f160af60920d (patch)
tree6c23ee30ef86aeebe0ff75d60881aa6561951c9a /lib/kobject.c
parent7c42721fe0c58a848849b43ff558cf2fb86aa35a (diff)
kobject: delayed kobject release: help find buggy drivers
Implement debugging for kobject release functions. kobjects are reference counted, so the drop of the last reference to them is not predictable. However, the common case is for the last reference to be the kobject's removal from a subsystem, which results in the release function being immediately called. This can hide subtle bugs, which can occur when another thread holds a reference to the kobject at the same time that a kobject is removed. This results in the release method being delayed. In order to make these kinds of problems more visible, the following patch implements a delayed release; this has the effect that the release function will be out of order with respect to the removal of the kobject in the same manner that it would be if a reference was being held. This provides us with an easy way to allow driver writers to debug their drivers and fix otherwise hidden problems. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'lib/kobject.c')
-rw-r--r--lib/kobject.c22
1 files changed, 19 insertions, 3 deletions
diff --git a/lib/kobject.c b/lib/kobject.c
index 4a1f33d43548..1d46c151a4ae 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -545,8 +545,8 @@ static void kobject_cleanup(struct kobject *kobj)
545 struct kobj_type *t = get_ktype(kobj); 545 struct kobj_type *t = get_ktype(kobj);
546 const char *name = kobj->name; 546 const char *name = kobj->name;
547 547
548 pr_debug("kobject: '%s' (%p): %s\n", 548 pr_debug("kobject: '%s' (%p): %s, parent %p\n",
549 kobject_name(kobj), kobj, __func__); 549 kobject_name(kobj), kobj, __func__, kobj->parent);
550 550
551 if (t && !t->release) 551 if (t && !t->release)
552 pr_debug("kobject: '%s' (%p): does not have a release() " 552 pr_debug("kobject: '%s' (%p): does not have a release() "
@@ -580,9 +580,25 @@ static void kobject_cleanup(struct kobject *kobj)
580 } 580 }
581} 581}
582 582
583#ifdef CONFIG_DEBUG_KOBJECT_RELEASE
584static void kobject_delayed_cleanup(struct work_struct *work)
585{
586 kobject_cleanup(container_of(to_delayed_work(work),
587 struct kobject, release));
588}
589#endif
590
583static void kobject_release(struct kref *kref) 591static void kobject_release(struct kref *kref)
584{ 592{
585 kobject_cleanup(container_of(kref, struct kobject, kref)); 593 struct kobject *kobj = container_of(kref, struct kobject, kref);
594#ifdef CONFIG_DEBUG_KOBJECT_RELEASE
595 pr_debug("kobject: '%s' (%p): %s, parent %p (delayed)\n",
596 kobject_name(kobj), kobj, __func__, kobj->parent);
597 INIT_DELAYED_WORK(&kobj->release, kobject_delayed_cleanup);
598 schedule_delayed_work(&kobj->release, HZ);
599#else
600 kobject_cleanup(kobj);
601#endif
586} 602}
587 603
588/** 604/**