Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Russell King and committed by
Greg Kroah-Hartman
c817a67e 7c42721f

+42 -3
+4
include/linux/kobject.h
··· 26 26 #include <linux/kernel.h> 27 27 #include <linux/wait.h> 28 28 #include <linux/atomic.h> 29 + #include <linux/workqueue.h> 29 30 30 31 #define UEVENT_HELPER_PATH_LEN 256 31 32 #define UEVENT_NUM_ENVP 32 /* number of env pointers */ ··· 66 65 struct kobj_type *ktype; 67 66 struct sysfs_dirent *sd; 68 67 struct kref kref; 68 + #ifdef CONFIG_DEBUG_KOBJECT_RELEASE 69 + struct delayed_work release; 70 + #endif 69 71 unsigned int state_initialized:1; 70 72 unsigned int state_in_sysfs:1; 71 73 unsigned int state_add_uevent_sent:1;
+19
lib/Kconfig.debug
··· 981 981 If you say Y here, some extra kobject debugging messages will be sent 982 982 to the syslog. 983 983 984 + config DEBUG_KOBJECT_RELEASE 985 + bool "kobject release debugging" 986 + depends on DEBUG_KERNEL 987 + help 988 + kobjects are reference counted objects. This means that their 989 + last reference count put is not predictable, and the kobject can 990 + live on past the point at which a driver decides to drop it's 991 + initial reference to the kobject gained on allocation. An 992 + example of this would be a struct device which has just been 993 + unregistered. 994 + 995 + However, some buggy drivers assume that after such an operation, 996 + the memory backing the kobject can be immediately freed. This 997 + goes completely against the principles of a refcounted object. 998 + 999 + If you say Y here, the kernel will delay the release of kobjects 1000 + on the last reference count to improve the visibility of this 1001 + kind of kobject release bug. 1002 + 984 1003 config HAVE_DEBUG_BUGVERBOSE 985 1004 bool 986 1005
+19 -3
lib/kobject.c
··· 545 545 struct kobj_type *t = get_ktype(kobj); 546 546 const char *name = kobj->name; 547 547 548 - pr_debug("kobject: '%s' (%p): %s\n", 549 - kobject_name(kobj), kobj, __func__); 548 + pr_debug("kobject: '%s' (%p): %s, parent %p\n", 549 + kobject_name(kobj), kobj, __func__, kobj->parent); 550 550 551 551 if (t && !t->release) 552 552 pr_debug("kobject: '%s' (%p): does not have a release() " ··· 580 580 } 581 581 } 582 582 583 + #ifdef CONFIG_DEBUG_KOBJECT_RELEASE 584 + static 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 + 583 591 static 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 /**