From: Tony B. <tb...@gm...> - 2006-03-09 23:10:03
|
Here is the patch. It adds a uevent to each block,char or bus device that you simply do the echo to at bootup. You have to remove udevstart starting from rc.udev. You also have to remove hotplug from the kernel. echo "/dev/null" > /proc/sys/kernel/hotplug You must remove hotplug before you start udev. This is how I would change rc.udev: put the echo "/dev/null" statement at the top. comment out all the udev stuff and jsut put this: /sbin/udevd --daemon Now add the for statements to echo the uevents. This should set everything up. Hotplug won't be needed as the kernel will send a uevent to udev and get things going that way. This, IMHO, is the way to go as it makes hotplugging and coldplugging a thing of the past and just leaves everything up to udev rules. You can leave udev at the version it is now and see how it works. After you patch the kernel, a "make oldconfig" should offer you the new option of sending uevents from the kernel. This whole method will be the easiest to manage as udev will be a one-stop shop for everything and then we can just concentrate on the udev rules to add function and improve device support and config. If this works, I would only offer this fix to those that have config problems today to see if it works for them. Making this mass deployment might create a headache if we encounter other issues. I am a huge proponent of the "if it ain't broke don't fix it" mentality. Moving forward, we need to upgrade udev to the latest anyway. Patch below between the hash lines ------------------------------------- diff --git a/drivers/base/class.c b/drivers/base/class.c --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -442,6 +442,13 @@ static ssize_t show_dev(struct class_dev =09return print_dev_t(buf, class_dev->devt); } +static ssize_t store_uevent(struct class_device *class_dev, +=09=09=09 const char *buf, size_t count) +{ +=09kobject_hotplug(&class_dev->kobj, KOBJ_ADD); +=09return count; +} + void class_device_initialize(struct class_device *class_dev) { =09kobj_set_kset_s(class_dev, class_obj_subsys); @@ -497,6 +504,12 @@ int class_device_add(struct class_device =09=09goto register_done; =09/* add the needed attributes to this device */ +=09class_dev->uevent_attr.attr.name =3D "uevent"; +=09class_dev->uevent_attr.attr.mode =3D S_IWUSR; +=09class_dev->uevent_attr.attr.owner =3D parent->owner; +=09class_dev->uevent_attr.store =3D store_uevent; +=09class_device_create_file(class_dev, &class_dev->uevent_attr); + =09if (MAJOR(class_dev->devt)) { =09=09struct class_device_attribute *attr; =09=09attr =3D kzalloc(sizeof(*attr), GFP_KERNEL); @@ -505,12 +518,10 @@ int class_device_add(struct class_device =09=09=09kobject_del(&class_dev->kobj); =09=09=09goto register_done; =09=09} - =09=09attr->attr.name =3D "dev"; =09=09attr->attr.mode =3D S_IRUGO; =09=09attr->attr.owner =3D parent->owner; =09=09attr->show =3D show_dev; -=09=09attr->store =3D NULL; =09=09class_device_create_file(class_dev, attr); =09=09class_dev->devt_attr =3D attr; =09} @@ -620,6 +631,7 @@ void class_device_del(struct class_devic =09=09sysfs_remove_link(&class_dev->kobj, "device"); =09=09sysfs_remove_link(&class_dev->dev->kobj, class_name); =09} +=09class_device_remove_file(class_dev, &class_dev->uevent_attr); =09if (class_dev->devt_attr) =09=09class_device_remove_file(class_dev, class_dev->devt_attr); =09class_device_remove_attrs(class_dev); diff --git a/drivers/base/core.c b/drivers/base/core.c --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -154,6 +154,13 @@ static struct kset_hotplug_ops device_ho =09.hotplug =3D=09dev_hotplug, }; +static ssize_t store_uevent(struct device *dev, struct device_attribute *a= ttr, +=09=09=09 const char *buf, size_t count) +{ +=09kobject_hotplug(&dev->kobj, KOBJ_ADD); +=09return count; +} + /** *=09device_subsys - structure to be registered with kobject core. */ @@ -258,6 +265,14 @@ int device_add(struct device *dev) =09if ((error =3D kobject_add(&dev->kobj))) =09=09goto Error; + +=09dev->uevent_attr.attr.name =3D "uevent"; +=09dev->uevent_attr.attr.mode =3D S_IWUSR; +=09if (dev->driver) +=09=09dev->uevent_attr.attr.owner =3D dev->driver->owner; +=09dev->uevent_attr.store =3D store_uevent; +=09device_create_file(dev, &dev->uevent_attr); + =09kobject_hotplug(&dev->kobj, KOBJ_ADD); =09if ((error =3D device_pm_add(dev))) =09=09goto PMError; @@ -349,6 +364,7 @@ void device_del(struct device * dev) =09if (parent) =09=09klist_del(&dev->knode_parent); +=09device_remove_file(dev, &dev->uevent_attr); =09/* Notify the platform of the removal, in case they =09 * need to do anything... diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c --- a/drivers/block/genhd.c +++ b/drivers/block/genhd.c @@ -337,10 +337,30 @@ static ssize_t disk_attr_show(struct kob =09return ret; } +static ssize_t disk_attr_store(struct kobject * kobj, struct attribute * a= ttr, +=09=09=09 const char *page, size_t count) +{ +=09struct gendisk *disk =3D to_disk(kobj); +=09struct disk_attribute *disk_attr =3D +=09=09container_of(attr,struct disk_attribute,attr); +=09ssize_t ret =3D 0; + +=09if (disk_attr->store) +=09=09ret =3D disk_attr->store(disk, page, count); +=09return ret; +} + static struct sysfs_ops disk_sysfs_ops =3D { =09.show=09=3D &disk_attr_show, +=09.store=09=3D &disk_attr_store, }; +static ssize_t disk_uevent_store(struct gendisk * disk, +=09=09=09=09 const char *buf, size_t count) +{ +=09kobject_hotplug(&disk->kobj, KOBJ_ADD); +=09return count; +} static ssize_t disk_dev_read(struct gendisk * disk, char *page) { =09dev_t base =3D MKDEV(disk->major, disk->first_minor); @@ -382,6 +402,10 @@ static ssize_t disk_stats_read(struct ge =09=09jiffies_to_msecs(disk_stat_read(disk, io_ticks)), =09=09jiffies_to_msecs(disk_stat_read(disk, time_in_queue))); } +static struct disk_attribute disk_attr_uevent =3D { +=09.attr =3D {.name =3D "uevent", .mode =3D S_IWUSR }, +=09.store=09=3D disk_uevent_store +}; static struct disk_attribute disk_attr_dev =3D { =09.attr =3D {.name =3D "dev", .mode =3D S_IRUGO }, =09.show=09=3D disk_dev_read @@ -404,6 +428,7 @@ static struct disk_attribute disk_attr_s }; static struct attribute * default_attrs[] =3D { +=09&disk_attr_uevent.attr, =09&disk_attr_dev.attr, =09&disk_attr_range.attr, =09&disk_attr_removable.attr, diff --git a/fs/partitions/check.c b/fs/partitions/check.c --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -192,6 +192,7 @@ check_partition(struct gendisk *hd, stru struct part_attribute { =09struct attribute attr; =09ssize_t (*show)(struct hd_struct *,char *); +=09ssize_t (*store)(struct hd_struct *,const char *, size_t); }; static ssize_t @@ -201,14 +202,33 @@ part_attr_show(struct kobject * kobj, st =09struct part_attribute * part_attr =3D container_of(attr,struct part_attribute,attr); =09ssize_t ret =3D 0; =09if (part_attr->show) -=09=09ret =3D part_attr->show(p,page); +=09=09ret =3D part_attr->show(p, page); +=09return ret; +} +static ssize_t +part_attr_store(struct kobject * kobj, struct attribute * attr, +=09=09const char *page, size_t count) +{ +=09struct hd_struct * p =3D container_of(kobj,struct hd_struct,kobj); +=09struct part_attribute * part_attr =3D container_of(attr,struct part_attribute,attr); +=09ssize_t ret =3D 0; + +=09if (part_attr->store) +=09=09ret =3D part_attr->store(p, page, count); =09return ret; } static struct sysfs_ops part_sysfs_ops =3D { =09.show=09=3D=09part_attr_show, +=09.store=09=3D=09part_attr_store, }; +static ssize_t part_uevent_store(struct hd_struct * p, +=09=09=09=09 const char *page, size_t count) +{ +=09kobject_hotplug(&p->kobj, KOBJ_ADD); +=09return count; +} static ssize_t part_dev_read(struct hd_struct * p, char *page) { =09struct gendisk *disk =3D container_of(p->kobj.parent,struct gendisk,kob= j); @@ -229,6 +249,10 @@ static ssize_t part_stat_read(struct hd_ =09=09 p->reads, (unsigned long long)p->read_sectors, =09=09 p->writes, (unsigned long long)p->write_sectors); } +static struct part_attribute part_attr_uevent =3D { +=09.attr =3D {.name =3D "uevent", .mode =3D S_IWUSR }, +=09.store=09=3D part_uevent_store +}; static struct part_attribute part_attr_dev =3D { =09.attr =3D {.name =3D "dev", .mode =3D S_IRUGO }, =09.show=09=3D part_dev_read @@ -247,6 +271,7 @@ static struct part_attribute part_attr_s }; static struct attribute * default_attrs[] =3D { +=09&part_attr_uevent.attr, =09&part_attr_dev.attr, =09&part_attr_start.attr, =09&part_attr_size.attr, diff --git a/include/linux/device.h b/include/linux/device.h --- a/include/linux/device.h +++ b/include/linux/device.h @@ -190,6 +190,18 @@ struct class_attribute class_attr_##_nam extern int class_create_file(struct class *, const struct class_attribute = *); extern void class_remove_file(struct class *, const struct class_attribute= *); +struct class_device_attribute { +=09struct attribute=09attr; +=09ssize_t (*show)(struct class_device *, char * buf); +=09ssize_t (*store)(struct class_device *, const char * buf, size_t count)= ; +}; + +#define CLASS_DEVICE_ATTR(_name,_mode,_show,_store)=09=09\ +struct class_device_attribute class_device_attr_##_name =3D =09\ +=09__ATTR(_name,_mode,_show,_store) + +extern int class_device_create_file(struct class_device *, +=09=09=09=09 const struct class_device_attribute *); struct class_device { =09struct list_head=09node; @@ -198,6 +210,7 @@ struct class_device { =09struct class=09=09* class;=09/* required */ =09dev_t=09=09=09devt;=09=09/* dev_t, creates the sysfs "dev" */ =09struct class_device_attribute *devt_attr; +=09struct class_device_attribute uevent_attr; =09struct device=09=09* dev;=09=09/* not necessary, but nice to have */ =09void=09=09=09* class_data;=09/* class-specific data */ @@ -228,18 +241,6 @@ extern int class_device_rename(struct cl extern struct class_device * class_device_get(struct class_device *); extern void class_device_put(struct class_device *); -struct class_device_attribute { -=09struct attribute=09attr; -=09ssize_t (*show)(struct class_device *, char * buf); -=09ssize_t (*store)(struct class_device *, const char * buf, size_t count)= ; -}; - -#define CLASS_DEVICE_ATTR(_name,_mode,_show,_store)=09=09\ -struct class_device_attribute class_device_attr_##_name =3D =09\ -=09__ATTR(_name,_mode,_show,_store) - -extern int class_device_create_file(struct class_device *, -=09=09=09=09 const struct class_device_attribute *); extern void class_device_remove_file(struct class_device *, =09=09=09=09 const struct class_device_attribute *); extern int class_device_create_bin_file(struct class_device *, @@ -266,6 +267,20 @@ extern struct class_device *class_device extern void class_device_destroy(struct class *cls, dev_t devt); +/* interface for exporting device attributes */ +struct device_attribute { +=09struct attribute=09attr; +=09ssize_t (*show)(struct device *dev, struct device_attribute *attr, +=09=09=09char *buf); +=09ssize_t (*store)(struct device *dev, struct device_attribute *attr, +=09=09=09 const char *buf, size_t count); +}; + +#define DEVICE_ATTR(_name,_mode,_show,_store) \ +struct device_attribute dev_attr_##_name =3D __ATTR(_name,_mode,_show,_sto= re) + +extern int device_create_file(struct device *device, struct device_attribute * entry); +extern void device_remove_file(struct device * dev, struct device_attribute * attr); struct device { =09struct klist=09=09klist_children; =09struct klist_node=09knode_parent;=09=09/* node in sibling list */ @@ -275,6 +290,7 @@ struct device { =09struct kobject kobj; =09char=09bus_id[BUS_ID_SIZE];=09/* position on parent bus */ +=09struct device_attribute uevent_attr; =09struct semaphore=09sem;=09/* semaphore to synchronize calls to =09=09=09=09=09 * its driver. @@ -343,23 +359,6 @@ extern int device_attach(struct device extern void driver_attach(struct device_driver * drv); -/* driverfs interface for exporting device attributes */ - -struct device_attribute { -=09struct attribute=09attr; -=09ssize_t (*show)(struct device *dev, struct device_attribute *attr, -=09=09=09char *buf); -=09ssize_t (*store)(struct device *dev, struct device_attribute *attr, -=09=09=09 const char *buf, size_t count); -}; - -#define DEVICE_ATTR(_name,_mode,_show,_store) \ -struct device_attribute dev_attr_##_name =3D __ATTR(_name,_mode,_show,_sto= re) - - -extern int device_create_file(struct device *device, struct device_attribute * entry); -extern void device_remove_file(struct device * dev, struct device_attribute * attr); - /* * Platform "fixup" functions - allow the platform to have their say * about devices and actions that the general device layer doesn't diff --git a/include/linux/genhd.h b/include/linux/genhd.h --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -132,6 +132,7 @@ struct gendisk { struct disk_attribute { =09struct attribute attr; =09ssize_t (*show)(struct gendisk *, char *); +=09ssize_t (*store)(struct gendisk *, const char *, size_t); }; /* --------------------------------------- On 3/9/06, John B <joh...@gm...> wrote: > > > On 3/9/06, Tony Brijeski <tb...@gm...> wrote: > > > Found a better patch but it is for the kernel. The uevent patch. It > > will be included in the 2.6.16 kernel so it might be best to just wait > > till 2.6.16 goes stable. > > > > These 3 lines will then replace the whole udevstart/coldplug issue and > > much better than udevsynthesize. > > > > for i in /sys/block/*/*/uevent; do echo 1 > $i; done > > for i in /sys/class/*/*/uevent; do echo 1 > $i; done > > for i in /sys/bus/*/devices/*/uevent; do echo 1 > $i; done > > > > Let me know what you folks think. I can patch the stock kernel we use > > if we want to play with it before 2.6.16 comes out. > > > > Tony, > > I wouldn't mind playing around with a pre-2.6.16 kernel patched with this > patch. FWIW, I have the source for 2.6.13 sitting on my box. If you can > let me know via a unified diff which file(s) need to be patched, I'll rol= l > my own 2.6.13 kernel for my box and see how well it works for me. ;-) > > Thanks, > John > |