diff options
-rw-r--r-- | drivers/base/core.c | 2 | ||||
-rw-r--r-- | include/linux/kobject.h | 17 |
2 files changed, 19 insertions, 0 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index 9a6c71038616..cf8c605ec32e 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1597,6 +1597,8 @@ static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir) return; mutex_lock(&gdp_mutex); + if (!kobject_has_children(glue_dir)) + kobject_del(glue_dir); kobject_put(glue_dir); mutex_unlock(&gdp_mutex); } diff --git a/include/linux/kobject.h b/include/linux/kobject.h index 7f6f93c3df9c..270b40515e79 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -116,6 +116,23 @@ extern void kobject_put(struct kobject *kobj); extern const void *kobject_namespace(struct kobject *kobj); extern char *kobject_get_path(struct kobject *kobj, gfp_t flag); +/** + * kobject_has_children - Returns whether a kobject has children. + * @kobj: the object to test + * + * This will return whether a kobject has other kobjects as children. + * + * It does NOT account for the presence of attribute files, only sub + * directories. It also assumes there is no concurrent addition or + * removal of such children, and thus relies on external locking. + */ +static inline bool kobject_has_children(struct kobject *kobj) +{ + WARN_ON_ONCE(kref_read(&kobj->kref) == 0); + + return kobj->sd && kobj->sd->dir.subdirs; +} + struct kobj_type { void (*release)(struct kobject *kobj); const struct sysfs_ops *sysfs_ops; |