aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorPatrick Mochel <mochel@osdl.org>2003-01-06 01:56:02 -0600
committerPatrick Mochel <mochel@osdl.org>2003-01-06 01:56:02 -0600
commit6fec616121f529857e6c68c584b7938dd568fbba (patch)
tree4f4bc88fa130b3440535b5fcbee51f5ebe4aba0d /lib
parent5c29ea4442e5139fb1fe5d3ead774e9206ef0324 (diff)
parent6ed6b9bf5b5d80581ebfcc3fa2738ee386b78cd1 (diff)
downloadhistory-6fec616121f529857e6c68c584b7938dd568fbba.tar.gz
Merge osdl.org:/home/mochel/src/kernel/devel/linux-2.5-core
into osdl.org:/home/mochel/src/kernel/devel/linux-2.5-kobject
Diffstat (limited to 'lib')
-rw-r--r--lib/kobject.c137
1 files changed, 103 insertions, 34 deletions
diff --git a/lib/kobject.c b/lib/kobject.c
index 24807bc72f81b8..59872973992a17 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -11,6 +11,14 @@
static spinlock_t kobj_lock = SPIN_LOCK_UNLOCKED;
+static inline struct kobj_type * get_ktype(struct kobject * k)
+{
+ if (k->kset && k->kset->ktype)
+ return k->kset->ktype;
+ else
+ return k->ktype;
+}
+
/**
* populate_dir - populate directory with attributes.
* @kobj: object we're working on.
@@ -25,13 +33,13 @@ static spinlock_t kobj_lock = SPIN_LOCK_UNLOCKED;
static int populate_dir(struct kobject * kobj)
{
- struct subsystem * s = kobj->subsys;
+ struct kobj_type * t = get_ktype(kobj);
struct attribute * attr;
int error = 0;
int i;
- if (s && s->default_attrs) {
- for (i = 0; (attr = s->default_attrs[i]); i++) {
+ if (t && t->default_attrs) {
+ for (i = 0; (attr = t->default_attrs[i]); i++) {
if ((error = sysfs_create_file(kobj,attr)))
break;
}
@@ -62,7 +70,7 @@ void kobject_init(struct kobject * kobj)
{
atomic_set(&kobj->refcount,1);
INIT_LIST_HEAD(&kobj->entry);
- kobj->subsys = subsys_get(kobj->subsys);
+ kobj->kset = kset_get(kobj->kset);
}
/**
@@ -73,7 +81,6 @@ void kobject_init(struct kobject * kobj)
int kobject_add(struct kobject * kobj)
{
int error = 0;
- struct subsystem * s = kobj->subsys;
struct kobject * parent;
if (!(kobj = kobject_get(kobj)))
@@ -81,19 +88,19 @@ int kobject_add(struct kobject * kobj)
parent = kobject_get(kobj->parent);
- pr_debug("kobject %s: registering. parent: %s, subsys: %s\n",
+ pr_debug("kobject %s: registering. parent: %s, set: %s\n",
kobj->name, parent ? parent->name : "<NULL>",
- kobj->subsys ? kobj->subsys->kobj.name : "<NULL>" );
+ kobj->kset ? kobj->kset->kobj.name : "<NULL>" );
- if (s) {
- down_write(&s->rwsem);
+ if (kobj->kset) {
+ down_write(&kobj->kset->subsys->rwsem);
if (parent)
list_add_tail(&kobj->entry,&parent->entry);
else {
- list_add_tail(&kobj->entry,&s->list);
- kobj->parent = kobject_get(&s->kobj);
+ list_add_tail(&kobj->entry,&kobj->kset->list);
+ kobj->parent = kobject_get(&kobj->kset->kobj);
}
- up_write(&s->rwsem);
+ up_write(&kobj->kset->subsys->rwsem);
}
error = create_dir(kobj);
if (error && parent)
@@ -127,10 +134,10 @@ int kobject_register(struct kobject * kobj)
void kobject_del(struct kobject * kobj)
{
sysfs_remove_dir(kobj);
- if (kobj->subsys) {
- down_write(&kobj->subsys->rwsem);
+ if (kobj->kset) {
+ down_write(&kobj->kset->subsys->rwsem);
list_del_init(&kobj->entry);
- up_write(&kobj->subsys->rwsem);
+ up_write(&kobj->kset->subsys->rwsem);
}
if (kobj->parent)
kobject_put(kobj->parent);
@@ -173,17 +180,14 @@ struct kobject * kobject_get(struct kobject * kobj)
void kobject_cleanup(struct kobject * kobj)
{
- struct subsystem * s = kobj->subsys;
+ struct kobj_type * t = get_ktype(kobj);
+ struct kset * s = kobj->kset;
pr_debug("kobject %s: cleaning up\n",kobj->name);
- if (s) {
- down_write(&s->rwsem);
- list_del_init(&kobj->entry);
- if (s->release)
- s->release(kobj);
- up_write(&s->rwsem);
- subsys_put(s);
- }
+ if (t && t->release)
+ t->release(kobj);
+ if (s)
+ kset_put(s);
}
/**
@@ -202,32 +206,97 @@ void kobject_put(struct kobject * kobj)
}
+/**
+ * kset_init - initialize a kset for use
+ * @k: kset
+ */
+
+void kset_init(struct kset * k)
+{
+ kobject_init(&k->kobj);
+ INIT_LIST_HEAD(&k->list);
+}
+
+
+/**
+ * kset_add - add a kset object to the hierarchy.
+ * @k: kset.
+ *
+ * Simply, this adds the kset's embedded kobject to the
+ * hierarchy.
+ * We also try to make sure that the kset's embedded kobject
+ * has a parent before it is added. We only care if the embedded
+ * kobject is not part of a kset itself, since kobject_add()
+ * assigns a parent in that case.
+ * If that is the case, and the kset has a controlling subsystem,
+ * then we set the kset's parent to be said subsystem.
+ */
+
+int kset_add(struct kset * k)
+{
+ if (!k->kobj.parent && !k->kobj.kset && k->subsys)
+ k->kobj.parent = &k->subsys->kset.kobj;
+
+ return kobject_add(&k->kobj);
+}
+
+
+/**
+ * kset_register - initialize and add a kset.
+ * @k: kset.
+ */
+
+int kset_register(struct kset * k)
+{
+ kset_init(k);
+ return kset_add(k);
+}
+
+
+/**
+ * kset_unregister - remove a kset.
+ * @k: kset.
+ */
+
+void kset_unregister(struct kset * k)
+{
+ kobject_unregister(&k->kobj);
+}
+
+
void subsystem_init(struct subsystem * s)
{
- kobject_init(&s->kobj);
init_rwsem(&s->rwsem);
- INIT_LIST_HEAD(&s->list);
+ kset_init(&s->kset);
}
/**
* subsystem_register - register a subsystem.
* @s: the subsystem we're registering.
+ *
+ * Once we register the subsystem, we want to make sure that
+ * the kset points back to this subsystem for correct usage of
+ * the rwsem.
*/
int subsystem_register(struct subsystem * s)
{
+ int error;
+
subsystem_init(s);
- if (s->parent)
- s->kobj.parent = &s->parent->kobj;
- pr_debug("subsystem %s: registering, parent: %s\n",
- s->kobj.name,s->parent ? s->parent->kobj.name : "<none>");
- return kobject_add(&s->kobj);
+ pr_debug("subsystem %s: registering\n",s->kobj.name);
+
+ if (!(error = kset_add(&s->kset))) {
+ if (!s->kset.subsys)
+ s->kset.subsys = s;
+ }
+ return error;
}
void subsystem_unregister(struct subsystem * s)
{
pr_debug("subsystem %s: unregistering\n",s->kobj.name);
- kobject_unregister(&s->kobj);
+ kset_unregister(&s->kset);
}
@@ -241,7 +310,7 @@ int subsys_create_file(struct subsystem * s, struct subsys_attribute * a)
{
int error = 0;
if (subsys_get(s)) {
- error = sysfs_create_file(&s->kobj,&a->attr);
+ error = sysfs_create_file(&s->kset.kobj,&a->attr);
subsys_put(s);
}
return error;
@@ -257,7 +326,7 @@ int subsys_create_file(struct subsystem * s, struct subsys_attribute * a)
void subsys_remove_file(struct subsystem * s, struct subsys_attribute * a)
{
if (subsys_get(s)) {
- sysfs_remove_file(&s->kobj,&a->attr);
+ sysfs_remove_file(&s->kset.kobj,&a->attr);
subsys_put(s);
}
}