aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2007-09-27 17:48:53 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2008-01-24 23:40:10 -0500
commitb727c702896f88d2ff6c3e03bd011d7c3dffe3e1 (patch)
tree772f0a3eb78a3e1d3475d36356bbff715a907829
parent12d03da7c19366268bdbc9fb0cd08d719c0cc283 (diff)
kset: add kset_create_and_add function
Now ksets can be dynamically created on the fly, no static definitions are required. Thanks to Miklos for hints on how to make this work better for the callers. And thanks to Kay for finding some stupid bugs in my original version and pointing out that we need to handle the fact that kobject's can have a kset as a parent and to handle that properly in kobject_add(). Cc: Kay Sievers <kay.sievers@vrfy.org> Cc: Miklos Szeredi <miklos@szeredi.hu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--include/linux/kobject.h4
-rw-r--r--lib/kobject.c92
2 files changed, 94 insertions, 2 deletions
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 0b97b3a53917..f91aeb745664 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -150,11 +150,13 @@ struct kset {
150 struct kset_uevent_ops *uevent_ops; 150 struct kset_uevent_ops *uevent_ops;
151}; 151};
152 152
153
154extern void kset_init(struct kset * k); 153extern void kset_init(struct kset * k);
155extern int __must_check kset_add(struct kset * k); 154extern int __must_check kset_add(struct kset * k);
156extern int __must_check kset_register(struct kset * k); 155extern int __must_check kset_register(struct kset * k);
157extern void kset_unregister(struct kset * k); 156extern void kset_unregister(struct kset * k);
157extern struct kset * __must_check kset_create_and_add(const char *name,
158 struct kset_uevent_ops *u,
159 struct kobject *parent_kobj);
158 160
159static inline struct kset * to_kset(struct kobject * kobj) 161static inline struct kset * to_kset(struct kobject * kobj)
160{ 162{
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
797static 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
804static 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 */
823static 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 */
861struct 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}
878EXPORT_SYMBOL_GPL(kset_create_and_add);
879
790EXPORT_SYMBOL(kobject_init); 880EXPORT_SYMBOL(kobject_init);
791EXPORT_SYMBOL(kobject_register); 881EXPORT_SYMBOL(kobject_register);
792EXPORT_SYMBOL(kobject_unregister); 882EXPORT_SYMBOL(kobject_unregister);