diff options
| author | Kay Sievers <kay.sievers@suse.de> | 2005-10-01 08:49:43 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-10-28 12:52:51 -0400 |
| commit | a7fd67062efc5b0fc9a61368c607fa92d1d57f9e (patch) | |
| tree | 8b91f198640608bd99f4e4764394e5134220abcf | |
| parent | d8539d81aeee4dbdc0624a798321e822fb2df7ae (diff) | |
[PATCH] add sysfs attr to re-emit device hotplug event
A "coldplug + udevstart" can be simple like this:
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
Signed-off-by: Kay Sievers <kay.sievers@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
| -rw-r--r-- | drivers/base/class.c | 16 | ||||
| -rw-r--r-- | drivers/base/core.c | 16 | ||||
| -rw-r--r-- | drivers/block/genhd.c | 25 | ||||
| -rw-r--r-- | fs/partitions/check.c | 27 | ||||
| -rw-r--r-- | include/linux/device.h | 57 | ||||
| -rw-r--r-- | include/linux/genhd.h | 1 |
6 files changed, 110 insertions, 32 deletions
diff --git a/drivers/base/class.c b/drivers/base/class.c index 73d44cf53db0..3cf6eb36f3d8 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c | |||
| @@ -442,6 +442,13 @@ static ssize_t show_dev(struct class_device *class_dev, char *buf) | |||
| 442 | return print_dev_t(buf, class_dev->devt); | 442 | return print_dev_t(buf, class_dev->devt); |
| 443 | } | 443 | } |
| 444 | 444 | ||
| 445 | static ssize_t store_uevent(struct class_device *class_dev, | ||
| 446 | const char *buf, size_t count) | ||
| 447 | { | ||
| 448 | kobject_hotplug(&class_dev->kobj, KOBJ_ADD); | ||
| 449 | return count; | ||
| 450 | } | ||
| 451 | |||
| 445 | void class_device_initialize(struct class_device *class_dev) | 452 | void class_device_initialize(struct class_device *class_dev) |
| 446 | { | 453 | { |
| 447 | kobj_set_kset_s(class_dev, class_obj_subsys); | 454 | kobj_set_kset_s(class_dev, class_obj_subsys); |
| @@ -497,6 +504,12 @@ int class_device_add(struct class_device *class_dev) | |||
| 497 | goto register_done; | 504 | goto register_done; |
| 498 | 505 | ||
| 499 | /* add the needed attributes to this device */ | 506 | /* add the needed attributes to this device */ |
| 507 | class_dev->uevent_attr.attr.name = "uevent"; | ||
| 508 | class_dev->uevent_attr.attr.mode = S_IWUSR; | ||
| 509 | class_dev->uevent_attr.attr.owner = parent->owner; | ||
| 510 | class_dev->uevent_attr.store = store_uevent; | ||
| 511 | class_device_create_file(class_dev, &class_dev->uevent_attr); | ||
| 512 | |||
| 500 | if (MAJOR(class_dev->devt)) { | 513 | if (MAJOR(class_dev->devt)) { |
| 501 | struct class_device_attribute *attr; | 514 | struct class_device_attribute *attr; |
| 502 | attr = kzalloc(sizeof(*attr), GFP_KERNEL); | 515 | attr = kzalloc(sizeof(*attr), GFP_KERNEL); |
| @@ -505,12 +518,10 @@ int class_device_add(struct class_device *class_dev) | |||
| 505 | kobject_del(&class_dev->kobj); | 518 | kobject_del(&class_dev->kobj); |
| 506 | goto register_done; | 519 | goto register_done; |
| 507 | } | 520 | } |
| 508 | |||
| 509 | attr->attr.name = "dev"; | 521 | attr->attr.name = "dev"; |
| 510 | attr->attr.mode = S_IRUGO; | 522 | attr->attr.mode = S_IRUGO; |
| 511 | attr->attr.owner = parent->owner; | 523 | attr->attr.owner = parent->owner; |
| 512 | attr->show = show_dev; | 524 | attr->show = show_dev; |
| 513 | attr->store = NULL; | ||
| 514 | class_device_create_file(class_dev, attr); | 525 | class_device_create_file(class_dev, attr); |
| 515 | class_dev->devt_attr = attr; | 526 | class_dev->devt_attr = attr; |
| 516 | } | 527 | } |
| @@ -621,6 +632,7 @@ void class_device_del(struct class_device *class_dev) | |||
| 621 | sysfs_remove_link(&class_dev->kobj, "device"); | 632 | sysfs_remove_link(&class_dev->kobj, "device"); |
| 622 | sysfs_remove_link(&class_dev->dev->kobj, class_name); | 633 | sysfs_remove_link(&class_dev->dev->kobj, class_name); |
| 623 | } | 634 | } |
| 635 | class_device_remove_file(class_dev, &class_dev->uevent_attr); | ||
| 624 | if (class_dev->devt_attr) | 636 | if (class_dev->devt_attr) |
| 625 | class_device_remove_file(class_dev, class_dev->devt_attr); | 637 | class_device_remove_file(class_dev, class_dev->devt_attr); |
| 626 | class_device_remove_attrs(class_dev); | 638 | class_device_remove_attrs(class_dev); |
diff --git a/drivers/base/core.c b/drivers/base/core.c index 31109193e2c4..ac4b5fdd95f5 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
| @@ -154,6 +154,13 @@ static struct kset_hotplug_ops device_hotplug_ops = { | |||
| 154 | .hotplug = dev_hotplug, | 154 | .hotplug = dev_hotplug, |
| 155 | }; | 155 | }; |
| 156 | 156 | ||
| 157 | static ssize_t store_uevent(struct device *dev, struct device_attribute *attr, | ||
| 158 | const char *buf, size_t count) | ||
| 159 | { | ||
| 160 | kobject_hotplug(&dev->kobj, KOBJ_ADD); | ||
| 161 | return count; | ||
| 162 | } | ||
| 163 | |||
| 157 | /** | 164 | /** |
| 158 | * device_subsys - structure to be registered with kobject core. | 165 | * device_subsys - structure to be registered with kobject core. |
| 159 | */ | 166 | */ |
| @@ -259,6 +266,14 @@ int device_add(struct device *dev) | |||
| 259 | 266 | ||
| 260 | if ((error = kobject_add(&dev->kobj))) | 267 | if ((error = kobject_add(&dev->kobj))) |
| 261 | goto Error; | 268 | goto Error; |
| 269 | |||
| 270 | dev->uevent_attr.attr.name = "uevent"; | ||
| 271 | dev->uevent_attr.attr.mode = S_IWUSR; | ||
| 272 | if (dev->driver) | ||
| 273 | dev->uevent_attr.attr.owner = dev->driver->owner; | ||
| 274 | dev->uevent_attr.store = store_uevent; | ||
| 275 | device_create_file(dev, &dev->uevent_attr); | ||
| 276 | |||
| 262 | kobject_hotplug(&dev->kobj, KOBJ_ADD); | 277 | kobject_hotplug(&dev->kobj, KOBJ_ADD); |
| 263 | if ((error = device_pm_add(dev))) | 278 | if ((error = device_pm_add(dev))) |
| 264 | goto PMError; | 279 | goto PMError; |
| @@ -350,6 +365,7 @@ void device_del(struct device * dev) | |||
| 350 | 365 | ||
| 351 | if (parent) | 366 | if (parent) |
| 352 | klist_del(&dev->knode_parent); | 367 | klist_del(&dev->knode_parent); |
| 368 | device_remove_file(dev, &dev->uevent_attr); | ||
| 353 | 369 | ||
| 354 | /* Notify the platform of the removal, in case they | 370 | /* Notify the platform of the removal, in case they |
| 355 | * need to do anything... | 371 | * need to do anything... |
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c index d42840cc0d1d..486ce1fdeb8c 100644 --- a/drivers/block/genhd.c +++ b/drivers/block/genhd.c | |||
| @@ -337,10 +337,30 @@ static ssize_t disk_attr_show(struct kobject *kobj, struct attribute *attr, | |||
| 337 | return ret; | 337 | return ret; |
| 338 | } | 338 | } |
| 339 | 339 | ||
| 340 | static ssize_t disk_attr_store(struct kobject * kobj, struct attribute * attr, | ||
| 341 | const char *page, size_t count) | ||
| 342 | { | ||
| 343 | struct gendisk *disk = to_disk(kobj); | ||
| 344 | struct disk_attribute *disk_attr = | ||
| 345 | container_of(attr,struct disk_attribute,attr); | ||
| 346 | ssize_t ret = 0; | ||
| 347 | |||
| 348 | if (disk_attr->store) | ||
| 349 | ret = disk_attr->store(disk, page, count); | ||
| 350 | return ret; | ||
| 351 | } | ||
| 352 | |||
| 340 | static struct sysfs_ops disk_sysfs_ops = { | 353 | static struct sysfs_ops disk_sysfs_ops = { |
| 341 | .show = &disk_attr_show, | 354 | .show = &disk_attr_show, |
| 355 | .store = &disk_attr_store, | ||
| 342 | }; | 356 | }; |
| 343 | 357 | ||
| 358 | static ssize_t disk_uevent_store(struct gendisk * disk, | ||
| 359 | const char *buf, size_t count) | ||
| 360 | { | ||
| 361 | kobject_hotplug(&disk->kobj, KOBJ_ADD); | ||
| 362 | return count; | ||
| 363 | } | ||
| 344 | static ssize_t disk_dev_read(struct gendisk * disk, char *page) | 364 | static ssize_t disk_dev_read(struct gendisk * disk, char *page) |
| 345 | { | 365 | { |
| 346 | dev_t base = MKDEV(disk->major, disk->first_minor); | 366 | dev_t base = MKDEV(disk->major, disk->first_minor); |
| @@ -382,6 +402,10 @@ static ssize_t disk_stats_read(struct gendisk * disk, char *page) | |||
| 382 | jiffies_to_msecs(disk_stat_read(disk, io_ticks)), | 402 | jiffies_to_msecs(disk_stat_read(disk, io_ticks)), |
| 383 | jiffies_to_msecs(disk_stat_read(disk, time_in_queue))); | 403 | jiffies_to_msecs(disk_stat_read(disk, time_in_queue))); |
| 384 | } | 404 | } |
| 405 | static struct disk_attribute disk_attr_uevent = { | ||
| 406 | .attr = {.name = "uevent", .mode = S_IWUSR }, | ||
| 407 | .store = disk_uevent_store | ||
| 408 | }; | ||
| 385 | static struct disk_attribute disk_attr_dev = { | 409 | static struct disk_attribute disk_attr_dev = { |
| 386 | .attr = {.name = "dev", .mode = S_IRUGO }, | 410 | .attr = {.name = "dev", .mode = S_IRUGO }, |
| 387 | .show = disk_dev_read | 411 | .show = disk_dev_read |
| @@ -404,6 +428,7 @@ static struct disk_attribute disk_attr_stat = { | |||
| 404 | }; | 428 | }; |
| 405 | 429 | ||
| 406 | static struct attribute * default_attrs[] = { | 430 | static struct attribute * default_attrs[] = { |
| 431 | &disk_attr_uevent.attr, | ||
| 407 | &disk_attr_dev.attr, | 432 | &disk_attr_dev.attr, |
| 408 | &disk_attr_range.attr, | 433 | &disk_attr_range.attr, |
| 409 | &disk_attr_removable.attr, | 434 | &disk_attr_removable.attr, |
diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 77e178f13162..d95a110293fa 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c | |||
| @@ -192,6 +192,7 @@ check_partition(struct gendisk *hd, struct block_device *bdev) | |||
| 192 | struct part_attribute { | 192 | struct part_attribute { |
| 193 | struct attribute attr; | 193 | struct attribute attr; |
| 194 | ssize_t (*show)(struct hd_struct *,char *); | 194 | ssize_t (*show)(struct hd_struct *,char *); |
| 195 | ssize_t (*store)(struct hd_struct *,const char *, size_t); | ||
| 195 | }; | 196 | }; |
| 196 | 197 | ||
| 197 | static ssize_t | 198 | static ssize_t |
| @@ -201,14 +202,33 @@ part_attr_show(struct kobject * kobj, struct attribute * attr, char * page) | |||
| 201 | struct part_attribute * part_attr = container_of(attr,struct part_attribute,attr); | 202 | struct part_attribute * part_attr = container_of(attr,struct part_attribute,attr); |
| 202 | ssize_t ret = 0; | 203 | ssize_t ret = 0; |
| 203 | if (part_attr->show) | 204 | if (part_attr->show) |
| 204 | ret = part_attr->show(p,page); | 205 | ret = part_attr->show(p, page); |
