diff options
Diffstat (limited to 'lib/kobject.c')
-rw-r--r-- | lib/kobject.c | 92 |
1 files changed, 91 insertions, 1 deletions
diff --git a/lib/kobject.c b/lib/kobject.c index 8f249408b2ec..4fb27ba28807 100644 --- a/lib/kobject.c +++ b/lib/kobject.c | |||
@@ -186,8 +186,15 @@ int kobject_add(struct kobject * kobj) | |||
186 | if (kobj->kset) { | 186 | if (kobj->kset) { |
187 | spin_lock(&kobj->kset->list_lock); | 187 | spin_lock(&kobj->kset->list_lock); |
188 | 188 | ||
189 | if (!parent) | 189 | if (!parent) { |
190 | parent = kobject_get(&kobj->kset->kobj); | 190 | parent = kobject_get(&kobj->kset->kobj); |
191 | /* | ||
192 | * If the kset is our parent, get a second | ||
193 | * reference, we drop both the kset and the | ||
194 | * parent ref on cleanup | ||
195 | */ | ||
196 | kobject_get(parent); | ||
197 | } | ||
191 | 198 | ||
192 | list_add_tail(&kobj->entry,&kobj->kset->list); | 199 | list_add_tail(&kobj->entry,&kobj->kset->list); |
193 | spin_unlock(&kobj->kset->list_lock); | 200 | spin_unlock(&kobj->kset->list_lock); |
@@ -787,6 +794,89 @@ int subsys_create_file(struct kset *s, struct subsys_attribute *a) | |||
787 | return error; | 794 | return error; |
788 | } | 795 | } |
789 | 796 | ||
797 | static void kset_release(struct kobject *kobj) | ||
798 | { | ||
799 | struct kset *kset = container_of(kobj, struct kset, kobj); | ||
800 | pr_debug("kset %s: now freed\n", kobject_name(kobj)); | ||
801 | kfree(kset); | ||
802 | } | ||
803 | |||
804 | static struct kobj_type kset_type = { | ||
805 | .release = kset_release, | ||
806 | }; | ||
807 | |||
808 | /** | ||
809 | * kset_create - create a struct kset dynamically | ||
810 | * | ||
811 | * @name: the name for the kset | ||
812 | * @uevent_ops: a struct kset_uevent_ops for the kset | ||
813 | * @parent_kobj: the parent kobject of this kset, if any. | ||
814 | * | ||
815 | * This function creates a kset structure dynamically. This structure can | ||
816 | * then be registered with the system and show up in sysfs with a call to | ||
817 | * kset_register(). When you are finished with this structure, if | ||
818 | * kset_register() has been called, call kset_unregister() and the | ||
819 | * structure will be dynamically freed when it is no longer being used. | ||
820 | * | ||
821 | * If the kset was not able to be created, NULL will be returned. | ||
822 | */ | ||
823 | static struct kset *kset_create(const char *name, | ||
824 | struct kset_uevent_ops *uevent_ops, | ||
825 | struct kobject *parent_kobj) | ||
826 | { | ||
827 | struct kset *kset; | ||
828 | |||
829 | kset = kzalloc(sizeof(*kset), GFP_KERNEL); | ||
830 | if (!kset) | ||
831 | return NULL; | ||
832 | kobject_set_name(&kset->kobj, name); | ||
833 | kset->uevent_ops = uevent_ops; | ||
834 | kset->kobj.parent = parent_kobj; | ||
835 | |||
836 | /* | ||
837 | * The kobject of this kset will have a type of kset_type and belong to | ||
838 | * no kset itself. That way we can properly free it when it is | ||
839 | * finished being used. | ||
840 | */ | ||
841 | kset->kobj.ktype = &kset_type; | ||
842 | kset->kobj.kset = NULL; | ||
843 | |||
844 | return kset; | ||
845 | } | ||
846 | |||
847 | /** | ||
848 | * kset_create_and_add - create a struct kset dynamically and add it to sysfs | ||
849 | * | ||
850 | * @name: the name for the kset | ||
851 | * @uevent_ops: a struct kset_uevent_ops for the kset | ||
852 | * @parent_kobj: the parent kobject of this kset, if any. | ||
853 | * | ||
854 | * This function creates a kset structure dynamically and registers it | ||
855 | * with sysfs. When you are finished with this structure, call | ||
856 | * kset_unregister() and the structure will be dynamically freed when it | ||
857 | * is no longer being used. | ||
858 | * | ||
859 | * If the kset was not able to be created, NULL will be returned. | ||
860 | */ | ||
861 | struct kset *kset_create_and_add(const char *name, | ||
862 | struct kset_uevent_ops *uevent_ops, | ||
863 | struct kobject *parent_kobj) | ||
864 | { | ||
865 | struct kset *kset; | ||
866 | int error; | ||
867 | |||
868 | kset = kset_create(name, uevent_ops, parent_kobj); | ||
869 | if (!kset) | ||
870 | return NULL; | ||
871 | error = kset_register(kset); | ||
872 | if (error) { | ||
873 | kfree(kset); | ||
874 | return NULL; | ||
875 | } | ||
876 | return kset; | ||
877 | } | ||
878 | EXPORT_SYMBOL_GPL(kset_create_and_add); | ||
879 | |||
790 | EXPORT_SYMBOL(kobject_init); | 880 | EXPORT_SYMBOL(kobject_init); |
791 | EXPORT_SYMBOL(kobject_register); | 881 | EXPORT_SYMBOL(kobject_register); |
792 | EXPORT_SYMBOL(kobject_unregister); | 882 | EXPORT_SYMBOL(kobject_unregister); |