Commit 3e815107 authored by Patrick Mochel's avatar Patrick Mochel

Introduce struct kset.

struct kset is what struct subsystem should have originally been called. It
is a set of kobjects, and nothing more, with a much less confusing name than
'subsystem.'

struct kset contains an embedded kobject, making it possible to represent it
in the object hierarchy, and sysfs. This also provides a means for objects
to easily express a list of subordinate objects. 

struct subsystem still exists, and contains an rwsem, which its subordinate
ksets use to protect their lists. 

An arbitrary number of ksets may belong to a subsystem. A ksets specifies
the subsystem it belongs to via its ->subsys field. 

struct subsystem also contains a default kset, which may be used without
having to define a separate kset. 

The objects that defined subordinate subsystems (bus and class drivers) have
been converted to use subordinate ksets instead.


Note that the usage of ksets is flexible. 
- ksets may contain a list of objects of any type, not just kobjects.
- The objects registered with a kset do not have to be registered.
- ksets themselves do not have to be registered. One can be used by
  simply calling kset_init(). 
- ksets do not need a name if they are not registered. 
- Note however that locking must be done manually in these cases.
parent 2e1c4037
...@@ -35,11 +35,12 @@ static struct kobj_type ktype_acpi_ns = { ...@@ -35,11 +35,12 @@ static struct kobj_type ktype_acpi_ns = {
.release = acpi_device_release, .release = acpi_device_release,
}; };
static struct subsystem acpi_namespace_subsys = { static struct kset acpi_namespace_kset = {
.kobj = { .kobj = {
.name = "namespace", .name = "namespace",
.parent = &acpi_subsys.kobj,
}, },
.subsys = &acpi_subsys,
.ktype = &ktype_acpi_ns,
}; };
...@@ -67,7 +68,7 @@ static void acpi_device_register(struct acpi_device * device, struct acpi_device ...@@ -67,7 +68,7 @@ static void acpi_device_register(struct acpi_device * device, struct acpi_device
if (parent) if (parent)
device->kobj.parent = &parent->kobj; device->kobj.parent = &parent->kobj;
device->kobj.ktype = &ktype_acpi_ns; device->kobj.ktype = &ktype_acpi_ns;
device->kobj.subsys = &acpi_namespace_subsys; device->kobj.kset = &acpi_namespace_kset;
kobject_register(&device->kobj); kobject_register(&device->kobj);
} }
...@@ -926,7 +927,7 @@ static int __init acpi_scan_init(void) ...@@ -926,7 +927,7 @@ static int __init acpi_scan_init(void)
if (acpi_disabled) if (acpi_disabled)
return_VALUE(0); return_VALUE(0);
subsystem_register(&acpi_namespace_subsys); kset_register(&acpi_namespace_kset);
/* /*
* Create the root device in the bus's device tree * Create the root device in the bus's device tree
......
...@@ -435,7 +435,6 @@ int bus_add_driver(struct device_driver * drv) ...@@ -435,7 +435,6 @@ int bus_add_driver(struct device_driver * drv)
{ {
struct bus_type * bus = get_bus(drv->bus); struct bus_type * bus = get_bus(drv->bus);
if (bus) { if (bus) {
down_write(&bus->subsys.rwsem);
pr_debug("bus %s: add driver %s\n",bus->name,drv->name); pr_debug("bus %s: add driver %s\n",bus->name,drv->name);
strncpy(drv->kobj.name,drv->name,KOBJ_NAME_LEN); strncpy(drv->kobj.name,drv->name,KOBJ_NAME_LEN);
...@@ -443,6 +442,7 @@ int bus_add_driver(struct device_driver * drv) ...@@ -443,6 +442,7 @@ int bus_add_driver(struct device_driver * drv)
drv->kobj.subsys = &bus->drivers; drv->kobj.subsys = &bus->drivers;
kobject_register(&drv->kobj); kobject_register(&drv->kobj);
down_write(&bus->subsys.rwsem);
devclass_add_driver(drv); devclass_add_driver(drv);
driver_attach(drv); driver_attach(drv);
up_write(&bus->subsys.rwsem); up_write(&bus->subsys.rwsem);
...@@ -467,8 +467,8 @@ void bus_remove_driver(struct device_driver * drv) ...@@ -467,8 +467,8 @@ void bus_remove_driver(struct device_driver * drv)
pr_debug("bus %s: remove driver %s\n",drv->bus->name,drv->name); pr_debug("bus %s: remove driver %s\n",drv->bus->name,drv->name);
driver_detach(drv); driver_detach(drv);
devclass_remove_driver(drv); devclass_remove_driver(drv);
kobject_unregister(&drv->kobj);
up_write(&drv->bus->subsys.rwsem); up_write(&drv->bus->subsys.rwsem);
kobject_unregister(&drv->kobj);
put_bus(drv->bus); put_bus(drv->bus);
} }
} }
...@@ -499,12 +499,12 @@ int bus_register(struct bus_type * bus) ...@@ -499,12 +499,12 @@ int bus_register(struct bus_type * bus)
subsystem_register(&bus->subsys); subsystem_register(&bus->subsys);
snprintf(bus->devices.kobj.name,KOBJ_NAME_LEN,"devices"); snprintf(bus->devices.kobj.name,KOBJ_NAME_LEN,"devices");
bus->devices.parent = &bus->subsys; bus->devices.subsys = &bus->subsys;
subsystem_register(&bus->devices); kset_register(&bus->devices);
snprintf(bus->drivers.kobj.name,KOBJ_NAME_LEN,"drivers"); snprintf(bus->drivers.kobj.name,KOBJ_NAME_LEN,"drivers");
bus->drivers.parent = &bus->subsys; bus->drivers.subsys = &bus->subsys;
subsystem_register(&bus->drivers); kset_register(&bus->drivers);
pr_debug("bus type '%s' registered\n",bus->name); pr_debug("bus type '%s' registered\n",bus->name);
return 0; return 0;
...@@ -521,8 +521,8 @@ int bus_register(struct bus_type * bus) ...@@ -521,8 +521,8 @@ int bus_register(struct bus_type * bus)
void bus_unregister(struct bus_type * bus) void bus_unregister(struct bus_type * bus)
{ {
pr_debug("bus %s: unregistering\n",bus->name); pr_debug("bus %s: unregistering\n",bus->name);
subsystem_unregister(&bus->drivers); kset_unregister(&bus->drivers);
subsystem_unregister(&bus->devices); kset_unregister(&bus->devices);
subsystem_unregister(&bus->subsys); subsystem_unregister(&bus->subsys);
} }
......
...@@ -86,7 +86,7 @@ int devclass_create_file(struct device_class * cls, struct devclass_attribute * ...@@ -86,7 +86,7 @@ int devclass_create_file(struct device_class * cls, struct devclass_attribute *
{ {
int error; int error;
if (cls) { if (cls) {
error = sysfs_create_file(&cls->subsys.kobj,&attr->attr); error = sysfs_create_file(&cls->subsys.kset.kobj,&attr->attr);
} else } else
error = -EINVAL; error = -EINVAL;
return error; return error;
...@@ -95,7 +95,7 @@ int devclass_create_file(struct device_class * cls, struct devclass_attribute * ...@@ -95,7 +95,7 @@ int devclass_create_file(struct device_class * cls, struct devclass_attribute *
void devclass_remove_file(struct device_class * cls, struct devclass_attribute * attr) void devclass_remove_file(struct device_class * cls, struct devclass_attribute * attr)
{ {
if (cls) if (cls)
sysfs_remove_file(&cls->subsys.kobj,&attr->attr); sysfs_remove_file(&cls->subsys.kset.kobj,&attr->attr);
} }
...@@ -234,12 +234,12 @@ int devclass_register(struct device_class * cls) ...@@ -234,12 +234,12 @@ int devclass_register(struct device_class * cls)
subsystem_register(&cls->subsys); subsystem_register(&cls->subsys);
snprintf(cls->devices.kobj.name,KOBJ_NAME_LEN,"devices"); snprintf(cls->devices.kobj.name,KOBJ_NAME_LEN,"devices");
cls->devices.parent = &cls->subsys; cls->devices.subsys = &cls->subsys;
subsystem_register(&cls->devices); kset_register(&cls->devices);
snprintf(cls->drivers.kobj.name,KOBJ_NAME_LEN,"drivers"); snprintf(cls->drivers.kobj.name,KOBJ_NAME_LEN,"drivers");
cls->drivers.parent = &cls->subsys; cls->drivers.subsys = &cls->subsys;
subsystem_register(&cls->drivers); kset_register(&cls->drivers);
return 0; return 0;
} }
...@@ -247,8 +247,8 @@ int devclass_register(struct device_class * cls) ...@@ -247,8 +247,8 @@ int devclass_register(struct device_class * cls)
void devclass_unregister(struct device_class * cls) void devclass_unregister(struct device_class * cls)
{ {
pr_debug("device class '%s': unregistering\n",cls->name); pr_debug("device class '%s': unregistering\n",cls->name);
subsystem_unregister(&cls->drivers); kset_unregister(&cls->drivers);
subsystem_unregister(&cls->devices); kset_unregister(&cls->devices);
subsystem_unregister(&cls->subsys); subsystem_unregister(&cls->subsys);
} }
......
...@@ -12,7 +12,7 @@ static struct subsystem firmware_subsys = { ...@@ -12,7 +12,7 @@ static struct subsystem firmware_subsys = {
int firmware_register(struct subsystem * s) int firmware_register(struct subsystem * s)
{ {
s->parent = &firmware_subsys; s->kobj.kset = &firmware_subsys.kset;
return subsystem_register(s); return subsystem_register(s);
} }
......
...@@ -25,7 +25,7 @@ static int intf_dev_link(struct intf_data * data) ...@@ -25,7 +25,7 @@ static int intf_dev_link(struct intf_data * data)
{ {
char name[16]; char name[16];
snprintf(name,16,"%d",data->intf_num); snprintf(name,16,"%d",data->intf_num);
return sysfs_create_link(&data->intf->subsys.kobj,&data->dev->kobj,name); return sysfs_create_link(&data->intf->subsys.kset.kobj,&data->dev->kobj,name);
} }
/** /**
...@@ -38,7 +38,7 @@ static void intf_dev_unlink(struct intf_data * data) ...@@ -38,7 +38,7 @@ static void intf_dev_unlink(struct intf_data * data)
{ {
char name[16]; char name[16];
snprintf(name,16,"%d",data->intf_num); snprintf(name,16,"%d",data->intf_num);
sysfs_remove_link(&data->intf->subsys.kobj,name); sysfs_remove_link(&data->intf->subsys.kset.kobj,name);
} }
...@@ -192,7 +192,7 @@ static void del_intf(struct device_interface * intf) ...@@ -192,7 +192,7 @@ static void del_intf(struct device_interface * intf)
struct list_head * entry; struct list_head * entry;
down_write(&intf->devclass->subsys.rwsem); down_write(&intf->devclass->subsys.rwsem);
list_for_each(entry,&intf->subsys.list) { list_for_each(entry,&intf->subsys.kset.list) {
struct intf_data * data = to_data(entry); struct intf_data * data = to_data(entry);
del(data); del(data);
} }
...@@ -241,7 +241,7 @@ int interface_add_dev(struct device * dev) ...@@ -241,7 +241,7 @@ int interface_add_dev(struct device * dev)
pr_debug("interfaces: adding device %s\n",dev->name); pr_debug("interfaces: adding device %s\n",dev->name);
list_for_each(node,&cls->subsys.list) { list_for_each(node,&cls->subsys.kset.list) {
struct device_interface * intf = to_intf(node); struct device_interface * intf = to_intf(node);
add(intf,dev); add(intf,dev);
} }
......
...@@ -38,7 +38,7 @@ int device_suspend(u32 state, u32 level) ...@@ -38,7 +38,7 @@ int device_suspend(u32 state, u32 level)
printk(KERN_EMERG "Suspending devices\n"); printk(KERN_EMERG "Suspending devices\n");
down_write(&device_subsys.rwsem); down_write(&device_subsys.rwsem);
list_for_each(node,&device_subsys.list) { list_for_each(node,&device_subsys.kset.list) {
struct device * dev = to_dev(node); struct device * dev = to_dev(node);
if (dev->driver && dev->driver->suspend) { if (dev->driver && dev->driver->suspend) {
pr_debug("suspending device %s\n",dev->name); pr_debug("suspending device %s\n",dev->name);
...@@ -64,7 +64,7 @@ void device_resume(u32 level) ...@@ -64,7 +64,7 @@ void device_resume(u32 level)
struct list_head * node; struct list_head * node;
down_write(&device_subsys.rwsem); down_write(&device_subsys.rwsem);
list_for_each_prev(node,&device_subsys.list) { list_for_each_prev(node,&device_subsys.kset.list) {
struct device * dev = to_dev(node); struct device * dev = to_dev(node);
if (dev->driver && dev->driver->resume) { if (dev->driver && dev->driver->resume) {
pr_debug("resuming device %s\n",dev->name); pr_debug("resuming device %s\n",dev->name);
...@@ -86,7 +86,7 @@ void device_shutdown(void) ...@@ -86,7 +86,7 @@ void device_shutdown(void)
printk(KERN_EMERG "Shutting down devices\n"); printk(KERN_EMERG "Shutting down devices\n");
down_write(&device_subsys.rwsem); down_write(&device_subsys.rwsem);
list_for_each(entry,&device_subsys.list) { list_for_each(entry,&device_subsys.kset.list) {
struct device * dev = to_dev(entry); struct device * dev = to_dev(entry);
if (dev->driver && dev->driver->shutdown) { if (dev->driver && dev->driver->shutdown) {
pr_debug("shutting down %s\n",dev->name); pr_debug("shutting down %s\n",dev->name);
......
...@@ -66,8 +66,8 @@ struct bus_type { ...@@ -66,8 +66,8 @@ struct bus_type {
char * name; char * name;
struct subsystem subsys; struct subsystem subsys;
struct subsystem drivers; struct kset drivers;
struct subsystem devices; struct kset devices;
int (*match)(struct device * dev, struct device_driver * drv); int (*match)(struct device * dev, struct device_driver * drv);
struct device * (*add) (struct device * parent, char * bus_id); struct device * (*add) (struct device * parent, char * bus_id);
...@@ -162,8 +162,8 @@ struct device_class { ...@@ -162,8 +162,8 @@ struct device_class {
u32 devnum; u32 devnum;
struct subsystem subsys; struct subsystem subsys;
struct subsystem devices; struct kset devices;
struct subsystem drivers; struct kset drivers;
int (*add_device)(struct device *); int (*add_device)(struct device *);
void (*remove_device)(struct device *); void (*remove_device)(struct device *);
......
...@@ -20,6 +20,7 @@ struct kobject { ...@@ -20,6 +20,7 @@ struct kobject {
struct list_head entry; struct list_head entry;
struct kobject * parent; struct kobject * parent;
struct subsystem * subsys; struct subsystem * subsys;
struct kset * kset;
struct kobj_type * ktype; struct kobj_type * ktype;
struct dentry * dentry; struct dentry * dentry;
}; };
...@@ -43,25 +44,70 @@ struct kobj_type { ...@@ -43,25 +44,70 @@ struct kobj_type {
struct attribute ** default_attrs; struct attribute ** default_attrs;
}; };
/**
* kset - a set of kobjects of a specific type, belonging
* to a specific subsystem.
*
* All kobjects of a kset should be embedded in an identical
* type. This type may have a descriptor, which the kset points
* to. This allows there to exist sets of objects of the same
* type in different subsystems.
*
* A subsystem does not have to be a list of only one type
* of object; multiple ksets can belong to one subsystem. All
* ksets of a subsystem share the subsystem's lock.
*
*/
struct kset {
struct subsystem * subsys;
struct kobj_type * ktype;
struct list_head list;
struct kobject kobj;
};
extern void kset_init(struct kset * k);
extern int kset_add(struct kset * k);
extern int kset_register(struct kset * k);
extern void kset_unregister(struct kset * k);
static inline struct kset * to_kset(struct kobject * kobj)
{
return container_of(kobj,struct kset,kobj);
}
static inline struct kset * kset_get(struct kset * k)
{
return k ? to_kset(kobject_get(&k->kobj)) : NULL;
}
static inline void kset_put(struct kset * k)
{
kobject_put(&k->kobj);
}
struct subsystem { struct subsystem {
struct kset kset;
struct kobject kobj; struct kobject kobj;
struct list_head list;
struct rw_semaphore rwsem; struct rw_semaphore rwsem;
struct subsystem * parent;
}; };
extern void subsystem_init(struct subsystem *); extern void subsystem_init(struct subsystem *);
extern int subsystem_register(struct subsystem *); extern int subsystem_register(struct subsystem *);
extern void subsystem_unregister(struct subsystem *); extern void subsystem_unregister(struct subsystem *);
static inline struct subsystem * subsys_get(struct subsystem * s) static inline struct subsystem * subsys_get(struct subsystem * s)
{ {
return s ? container_of(kobject_get(&s->kobj),struct subsystem,kobj) : NULL; return s ? container_of(kset_get(&s->kset),struct subsystem,kset) : NULL;
} }
static inline void subsys_put(struct subsystem * s) static inline void subsys_put(struct subsystem * s)
{ {
kobject_put(&s->kobj); kset_put(&s->kset);
} }
struct subsys_attribute { struct subsys_attribute {
...@@ -73,4 +119,5 @@ struct subsys_attribute { ...@@ -73,4 +119,5 @@ struct subsys_attribute {
extern int subsys_create_file(struct subsystem * , struct subsys_attribute *); extern int subsys_create_file(struct subsystem * , struct subsys_attribute *);
extern void subsys_remove_file(struct subsystem * , struct subsys_attribute *); extern void subsys_remove_file(struct subsystem * , struct subsys_attribute *);
#endif /* _KOBJECT_H_ */ #endif /* _KOBJECT_H_ */
...@@ -62,7 +62,7 @@ void kobject_init(struct kobject * kobj) ...@@ -62,7 +62,7 @@ void kobject_init(struct kobject * kobj)
{ {
atomic_set(&kobj->refcount,1); atomic_set(&kobj->refcount,1);
INIT_LIST_HEAD(&kobj->entry); INIT_LIST_HEAD(&kobj->entry);
kobj->subsys = subsys_get(kobj->subsys); kobj->kset = kset_get(kobj->kset);
} }
/** /**
...@@ -73,7 +73,6 @@ void kobject_init(struct kobject * kobj) ...@@ -73,7 +73,6 @@ void kobject_init(struct kobject * kobj)
int kobject_add(struct kobject * kobj) int kobject_add(struct kobject * kobj)
{ {
int error = 0; int error = 0;
struct subsystem * s = kobj->subsys;
struct kobject * parent; struct kobject * parent;
if (!(kobj = kobject_get(kobj))) if (!(kobj = kobject_get(kobj)))
...@@ -81,19 +80,24 @@ int kobject_add(struct kobject * kobj) ...@@ -81,19 +80,24 @@ int kobject_add(struct kobject * kobj)
parent = kobject_get(kobj->parent); 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->name, parent ? parent->name : "<NULL>",
kobj->subsys ? kobj->subsys->kobj.name : "<NULL>" ); kobj->kset ? kobj->kset->kobj.name : "<NULL>" );
if (s) { if (kobj->subsys) {
down_write(&s->rwsem); if (!kobj->kset)
kobj->kset = &kobj->subsys->kset;
}
if (kobj->kset) {
down_write(&kobj->kset->subsys->rwsem);
if (parent) if (parent)
list_add_tail(&kobj->entry,&parent->entry); list_add_tail(&kobj->entry,&parent->entry);
else { else {
list_add_tail(&kobj->entry,&s->list); list_add_tail(&kobj->entry,&kobj->kset->list);
kobj->parent = kobject_get(&s->kobj); kobj->parent = kobject_get(&kobj->kset->kobj);
} }
up_write(&s->rwsem); up_write(&kobj->kset->subsys->rwsem);
} }
error = create_dir(kobj); error = create_dir(kobj);
if (error && parent) if (error && parent)
...@@ -127,10 +131,10 @@ int kobject_register(struct kobject * kobj) ...@@ -127,10 +131,10 @@ int kobject_register(struct kobject * kobj)
void kobject_del(struct kobject * kobj) void kobject_del(struct kobject * kobj)
{ {
sysfs_remove_dir(kobj); sysfs_remove_dir(kobj);
if (kobj->subsys) { if (kobj->kset) {
down_write(&kobj->subsys->rwsem); down_write(&kobj->kset->subsys->rwsem);
list_del_init(&kobj->entry); list_del_init(&kobj->entry);
up_write(&kobj->subsys->rwsem); up_write(&kobj->kset->subsys->rwsem);
} }
if (kobj->parent) if (kobj->parent)
kobject_put(kobj->parent); kobject_put(kobj->parent);
...@@ -174,17 +178,13 @@ struct kobject * kobject_get(struct kobject * kobj) ...@@ -174,17 +178,13 @@ struct kobject * kobject_get(struct kobject * kobj)
void kobject_cleanup(struct kobject * kobj) void kobject_cleanup(struct kobject * kobj)
{ {
struct kobj_type * t = kobj->ktype; struct kobj_type * t = kobj->ktype;
struct subsystem * s = kobj->subsys; struct kset * s = kobj->kset;
pr_debug("kobject %s: cleaning up\n",kobj->name); pr_debug("kobject %s: cleaning up\n",kobj->name);
if (s) {
down_write(&s->rwsem);
list_del_init(&kobj->entry);
up_write(&s->rwsem);
subsys_put(s);
}
if (t && t->release) if (t && t->release)
t->release(kobj); t->release(kobj);
if (s)
kset_put(s);
} }
/** /**
...@@ -203,32 +203,98 @@ void kobject_put(struct kobject * kobj) ...@@ -203,32 +203,98 @@ 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) void subsystem_init(struct subsystem * s)
{ {
kobject_init(&s->kobj); memcpy(&s->kset.kobj,&s->kobj,sizeof(struct kobject));
init_rwsem(&s->rwsem); init_rwsem(&s->rwsem);
INIT_LIST_HEAD(&s->list); kset_init(&s->kset);
} }
/** /**
* subsystem_register - register a subsystem. * subsystem_register - register a subsystem.
* @s: the subsystem we're registering. * @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 subsystem_register(struct subsystem * s)
{ {
int error;
subsystem_init(s); subsystem_init(s);
if (s->parent) pr_debug("subsystem %s: registering\n",s->kobj.name);
s->kobj.parent = &s->parent->kobj;
pr_debug("subsystem %s: registering, parent: %s\n", if (!(error = kset_add(&s->kset))) {
s->kobj.name,s->parent ? s->parent->kobj.name : "<none>"); if (!s->kset.subsys)
return kobject_add(&s->kobj); s->kset.subsys = s;
}
return error;
} }
void subsystem_unregister(struct subsystem * s) void subsystem_unregister(struct subsystem * s)
{ {
pr_debug("subsystem %s: unregistering\n",s->kobj.name); pr_debug("subsystem %s: unregistering\n",s->kobj.name);
kobject_unregister(&s->kobj); kset_unregister(&s->kset);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment