Commit 23066070 authored by Patrick Mochel's avatar Patrick Mochel

kobject: Introduce struct kobj_type.

This is the first step in morphing struct subsystem into something meaningful.

A subsystem is defined simply as a list of kobjects of a certain type, which
is far too generic. A subsystem should be representative of a large entity
of code (i.e. a subsystem of the kernel), not just a simple list. 

This changeset:

- Creates struct kobj_type, a descriptor of the type a kobject is embedded
  in.

- Extracts the fields that are specific to a particular object type from
  struct subsystem and puts them in struct kobj_type, which are
  - the object's release method.
  - the sysfs operations for the object type.
  - the default attributes of the object type.

- Adds ptr to struct kobject to point to its type descriptor. 

- Converts the existing subsystem definitions to define struct kobj_type. 


struct kobj_type's are not registered, as they do not have any explicit
representation in the object hierarchy, nor do they have any fields that
need runtime initialization. 

A kobject's ktype should be set when it is registered, like its subsystem.
Note this obviates the need for defining a struct subsystem when an object
type does not need to be kept in a global list. 
parent 509b39b1
......@@ -31,12 +31,17 @@ static void acpi_device_release(struct kobject * kobj)
kfree(dev);
}
static struct subsystem acpi_namespace_subsys = {
.kobj = { .name = "namespace" },
.parent = &acpi_subsys,
static struct kobj_type ktype_acpi_ns = {
.release = acpi_device_release,
};
static struct subsystem acpi_namespace_subsys = {
.kobj = {
.name = "namespace",
.parent = &acpi_subsys.kobj,
},
};
static void acpi_device_register(struct acpi_device * device, struct acpi_device * parent)
{
......@@ -61,6 +66,7 @@ static void acpi_device_register(struct acpi_device * device, struct acpi_device
strncpy(device->kobj.name,device->pnp.bus_id,KOBJ_NAME_LEN);
if (parent)
device->kobj.parent = &parent->kobj;
device->kobj.ktype = &ktype_acpi_ns;
device->kobj.subsys = &acpi_namespace_subsys;
kobject_register(&device->kobj);
}
......
......@@ -70,6 +70,11 @@ static void driver_release(struct kobject * kobj)
up(&drv->unload_sem);
}
static struct kobj_type ktype_driver = {
.sysfs_ops = &driver_sysfs_ops,
.release = driver_release,
};
/*
* sysfs bindings for buses
......@@ -126,9 +131,13 @@ void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr)
}
}
static struct kobj_type ktype_bus = {
.sysfs_ops = &bus_sysfs_ops,
};
struct subsystem bus_subsys = {
.kobj = { .name = "bus" },
.sysfs_ops = &bus_sysfs_ops,
};
......@@ -432,6 +441,7 @@ int bus_add_driver(struct device_driver * drv)
pr_debug("bus %s: add driver %s\n",bus->name,drv->name);
strncpy(drv->kobj.name,drv->name,KOBJ_NAME_LEN);
drv->kobj.ktype = &ktype_driver;
drv->kobj.subsys = &bus->drvsubsys;
kobject_register(&drv->kobj);
......@@ -491,7 +501,8 @@ int bus_register(struct bus_type * bus)
down(&bus_sem);
strncpy(bus->subsys.kobj.name,bus->name,KOBJ_NAME_LEN);
bus->subsys.parent = &bus_subsys;
bus->subsys.kobj.ktype = &ktype_bus;
bus->subsys.kobj.subsys = &bus_subsys;
subsystem_register(&bus->subsys);
snprintf(bus->devsubsys.kobj.name,KOBJ_NAME_LEN,"devices");
......@@ -500,8 +511,6 @@ int bus_register(struct bus_type * bus)
snprintf(bus->drvsubsys.kobj.name,KOBJ_NAME_LEN,"drivers");
bus->drvsubsys.parent = &bus->subsys;
bus->drvsubsys.sysfs_ops = &driver_sysfs_ops;
bus->drvsubsys.release = driver_release;
subsystem_register(&bus->drvsubsys);
pr_debug("bus type '%s' registered\n",bus->name);
......
......@@ -46,9 +46,12 @@ static struct sysfs_ops class_sysfs_ops = {
.store = devclass_attr_store,
};
static struct kobj_type ktype_devclass = {
.sysfs_ops = &class_sysfs_ops,
};
static struct subsystem class_subsys = {
.kobj = { .name = "class", },
.sysfs_ops = &class_sysfs_ops,
};
......@@ -231,7 +234,8 @@ int devclass_register(struct device_class * cls)
pr_debug("device class '%s': registering\n",cls->name);
strncpy(cls->subsys.kobj.name,cls->name,KOBJ_NAME_LEN);
cls->subsys.parent = &class_subsys;
cls->subsys.kobj.subsys = &class_subsys;
cls->subsys.kobj.ktype = &ktype_devclass;
subsystem_register(&cls->subsys);
snprintf(cls->devsubsys.kobj.name,KOBJ_NAME_LEN,"devices");
......
......@@ -81,6 +81,11 @@ static void device_release(struct kobject * kobj)
dev->release(dev);
}
static struct kobj_type ktype_device = {
.release = device_release,
.sysfs_ops = &dev_sysfs_ops,
.default_attrs = dev_default_attrs,
};
/**
* device_subsys - structure to be registered with kobject core.
......@@ -89,9 +94,6 @@ struct subsystem device_subsys = {
.kobj = {
.name = "devices",
},
.release = device_release,
.sysfs_ops = &dev_sysfs_ops,
.default_attrs = dev_default_attrs,
};
......@@ -175,6 +177,7 @@ int device_add(struct device *dev)
/* first, register with generic layer. */
strncpy(dev->kobj.name,dev->bus_id,KOBJ_NAME_LEN);
dev->kobj.ktype = &ktype_device;
dev->kobj.subsys = &device_subsys;
if (parent)
dev->kobj.parent = &parent->kobj;
......
......@@ -384,13 +384,16 @@ static void disk_release(struct kobject * kobj)
kfree(disk);
}
struct subsystem block_subsys = {
.kobj = { .name = "block" },
static struct kobj_type ktype_block = {
.release = disk_release,
.sysfs_ops = &disk_sysfs_ops,
.default_attrs = default_attrs,
};
struct subsystem block_subsys = {
.kobj = { .name = "block" },
};
struct gendisk *alloc_disk(int minors)
{
struct gendisk *disk = kmalloc(sizeof(struct gendisk), GFP_KERNEL);
......@@ -409,6 +412,7 @@ struct gendisk *alloc_disk(int minors)
while (minors >>= 1)
disk->minor_shift++;
disk->kobj.subsys = &block_subsys;
disk->kobj.ktype = &ktype_block;
kobject_init(&disk->kobj);
INIT_LIST_HEAD(&disk->full_list);
rand_initialize_disk(disk);
......
......@@ -344,19 +344,11 @@ static struct attribute * default_attrs[] = {
extern struct subsystem block_subsys;
static struct subsystem part_subsys = {
.parent = &block_subsys,
static struct kobj_type ktype_part = {
.default_attrs = default_attrs,
.sysfs_ops = &part_sysfs_ops,
};
static int __init part_subsys_init(void)
{
return subsystem_register(&part_subsys);
}
__initcall(part_subsys_init);
void delete_partition(struct gendisk *disk, int part)
{
struct hd_struct *p = disk->part + part - 1;
......@@ -378,7 +370,7 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len)
devfs_register_partition(disk, part);
snprintf(p->kobj.name,KOBJ_NAME_LEN,"%s%d",disk->kobj.name,part);
p->kobj.parent = &disk->kobj;
p->kobj.subsys = &part_subsys;
p->kobj.ktype = &ktype_part;
kobject_register(&p->kobj);
}
......
......@@ -303,11 +303,11 @@ static int check_perm(struct inode * inode, struct file * file)
if (!kobj || !attr)
goto Einval;
/* if the kobject has no subsystem, then it is a subsystem itself,
* so give it the subsys_sysfs_ops.
/* if the kobject has no ktype, then we assume that it is a subsystem
* itself, and use ops for it.
*/
if (kobj->subsys)
ops = kobj->subsys->sysfs_ops;
if (kobj->ktype)
ops = kobj->ktype->sysfs_ops;
else
ops = &subsys_sysfs_ops;
......
......@@ -20,6 +20,7 @@ struct kobject {
struct list_head entry;
struct kobject * parent;
struct subsystem * subsys;
struct kobj_type * ktype;
struct dentry * dentry;
};
......@@ -36,14 +37,17 @@ extern struct kobject * kobject_get(struct kobject *);
extern void kobject_put(struct kobject *);
struct kobj_type {
void (*release)(struct kobject *);
struct sysfs_ops * sysfs_ops;
struct attribute ** default_attrs;
};
struct subsystem {
struct kobject kobj;
struct list_head list;
struct rw_semaphore rwsem;
struct subsystem * parent;
void (*release)(struct kobject *);
struct sysfs_ops * sysfs_ops;
struct attribute ** default_attrs;
};
extern void subsystem_init(struct subsystem *);
......
......@@ -25,13 +25,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 = kobj->ktype;
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;
}
......@@ -173,17 +173,18 @@ struct kobject * kobject_get(struct kobject * kobj)
void kobject_cleanup(struct kobject * kobj)
{
struct kobj_type * t = kobj->ktype;
struct subsystem * s = kobj->subsys;
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);
}
/**
......
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