aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKay Sievers <kay.sievers@suse.de>2005-10-01 08:49:43 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-10-28 12:52:51 -0400
commita7fd67062efc5b0fc9a61368c607fa92d1d57f9e (patch)
tree8b91f198640608bd99f4e4764394e5134220abcf
parentd8539d81aeee4dbdc0624a798321e822fb2df7ae (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.c16
-rw-r--r--drivers/base/core.c16
-rw-r--r--drivers/block/genhd.c25
-rw-r--r--fs/partitions/check.c27
-rw-r--r--include/linux/device.h57
-rw-r--r--include/linux/genhd.h1
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
445static 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
445void class_device_initialize(struct class_device *class_dev) 452void 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
157static 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
340static 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
340static struct sysfs_ops disk_sysfs_ops = { 353static 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
358static 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}
344static ssize_t disk_dev_read(struct gendisk * disk, char *page) 364static 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}
405static struct disk_attribute disk_attr_uevent = {
406 .attr = {.name = "uevent", .mode = S_IWUSR },
407 .store = disk_uevent_store
408};
385static struct disk_attribute disk_attr_dev = { 409static 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
406static struct attribute * default_attrs[] = { 430static 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)
192struct part_attribute { 192struct 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
197static ssize_t 198static 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);
206 return ret;
207}
208static ssize_t
209part_attr_store(struct kobject * kobj, struct attribute * attr,
210 const char *page, size_t count)
211{
212 struct hd_struct * p = container_of(kobj,struct hd_struct,kobj);
213 struct part_attribute * part_attr = container_of(attr,struct part_attribute,attr);
214 ssize_t ret = 0;
215
216 if (part_attr->store)
217 ret = part_attr->store(p, page, count);
205 return ret; 218 return ret;
206} 219}
207 220
208static struct sysfs_ops part_sysfs_ops = { 221static struct sysfs_ops part_sysfs_ops = {
209 .show = part_attr_show, 222 .show = part_attr_show,
223 .store = part_attr_store,
210}; 224};
211 225
226static ssize_t part_uevent_store(struct hd_struct * p,
227 const char *page, size_t count)
228{
229 kobject_hotplug(&p->kobj, KOBJ_ADD);
230 return count;
231}
212static ssize_t part_dev_read(struct hd_struct * p, char *page) 232static ssize_t part_dev_read(struct hd_struct * p, char *page)
213{ 233{
214 struct gendisk *disk = container_of(p->kobj.parent,struct gendisk,kobj); 234 struct gendisk *disk = container_of(p->kobj.parent,struct gendisk,kobj);
@@ -229,6 +249,10 @@ static ssize_t part_stat_read(struct hd_struct * p, char *page)
229 p->reads, (unsigned long long)p->read_sectors, 249 p->reads, (unsigned long long)p->read_sectors,
230 p->writes, (unsigned long long)p->write_sectors); 250 p->writes, (unsigned long long)p->write_sectors);
231} 251}
252static struct part_attribute part_attr_uevent = {
253 .attr = {.name = "uevent", .mode = S_IWUSR },
254 .store = part_uevent_store
255};
232static struct part_attribute part_attr_dev = { 256static struct part_attribute part_attr_dev = {
233 .attr = {.name = "dev", .mode = S_IRUGO }, 257 .attr = {.name = "dev", .mode = S_IRUGO },
234 .show = part_dev_read 258 .show = part_dev_read
@@ -247,6 +271,7 @@ static struct part_attribute part_attr_stat = {
247}; 271};
248 272
249static struct attribute * default_attrs[] = { 273static struct attribute * default_attrs[] = {
274 &part_attr_uevent.attr,
250 &part_attr_dev.attr, 275 &part_attr_dev.attr,
251 &part_attr_start.attr, 276 &part_attr_start.attr,
252 &part_attr_size.attr, 277 &part_attr_size.attr,
diff --git a/include/linux/device.h b/include/linux/device.h
index a53a822c4d16..e86a580b72e1 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -190,6 +190,18 @@ struct class_attribute class_attr_##_name = __ATTR(_name,_mode,_show,_store)
190extern int class_create_file(struct class *, const struct class_attribute *); 190extern int class_create_file(struct class *, const struct class_attribute *);
191extern void class_remove_file(struct class *, const struct class_attribute *); 191extern void class_remove_file(struct class *, const struct class_attribute *);
192 192
193struct class_device_attribute {
194 struct attribute attr;
195 ssize_t (*show)(struct class_device *, char * buf);
196 ssize_t (*store)(struct class_device *, const char * buf, size_t count);
197};
198
199#define CLASS_DEVICE_ATTR(_name,_mode,_show,_store) \
200struct class_device_attribute class_device_attr_##_name = \
201 __ATTR(_name,_mode,_show,_store)
202
203extern int class_device_create_file(struct class_device *,
204 const struct class_device_attribute *);
193 205
194struct class_device { 206struct class_device {
195 struct list_head node; 207 struct list_head node;
@@ -198,6 +210,7 @@ struct class_device {
198 struct class * class; /* required */ 210 struct class * class; /* required */
199 dev_t devt; /* dev_t, creates the sysfs "dev" */ 211 dev_t devt; /* dev_t, creates the sysfs "dev" */
200 struct class_device_attribute *devt_attr; 212 struct class_device_attribute *devt_attr;
213 struct class_device_attribute uevent_attr;
201 struct device * dev; /* not necessary, but nice to have */ 214 struct device * dev; /* not necessary, but nice to have */
202 void * class_data; /* class-specific data */ 215 void * class_data; /* class-specific data */
203 216
@@ -228,18 +241,6 @@ extern int class_device_rename(struct class_device *, char *);
228extern struct class_device * class_device_get(struct class_device *); 241extern struct class_device * class_device_get(struct class_device *);
229extern void class_device_put(struct class_device *); 242extern void class_device_put(struct class_device *);
230 243
231struct class_device_attribute {
232 struct attribute attr;
233 ssize_t (*show)(struct class_device *, char * buf);
234 ssize_t (*store)(struct class_device *, const char * buf, size_t count);
235};
236
237#define CLASS_DEVICE_ATTR(_name,_mode,_show,_store) \
238struct class_device_attribute class_device_attr_##_name = \
239 __ATTR(_name,_mode,_show,_store)
240
241extern int class_device_create_file(struct class_device *,
242 const struct class_device_attribute *);
243extern void class_device_remove_file(struct class_device *, 244extern void class_device_remove_file(struct class_device *,
244 const struct class_device_attribute *); 245 const struct class_device_attribute *);
245extern int class_device_create_bin_file(struct class_device *, 246extern int class_device_create_bin_file(struct class_device *,
@@ -266,6 +267,20 @@ extern struct class_device *class_device_create(struct class *cls, dev_t devt,
266extern void class_device_destroy(struct class *cls, dev_t devt); 267extern void class_device_destroy(struct class *cls, dev_t devt);
267 268
268 269
270/* interface for exporting device attributes */
271struct device_attribute {
272 struct attribute attr;
273 ssize_t (*show)(struct device *dev, struct device_attribute *attr,
274 char *buf);
275 ssize_t (*store)(struct device *dev, struct device_attribute *attr,
276 const char *buf, size_t count);
277};
278
279#define DEVICE_ATTR(_name,_mode,_show,_store) \
280struct device_attribute dev_attr_##_name = __ATTR(_name,_mode,_show,_store)
281
282extern int device_create_file(struct device *device, struct device_attribute * entry);
283extern void device_remove_file(struct device * dev, struct device_attribute * attr);
269struct device { 284struct device {
270 struct klist klist_children; 285 struct klist klist_children;
271 struct klist_node knode_parent; /* node in sibling list */ 286 struct klist_node knode_parent; /* node in sibling list */
@@ -275,6 +290,7 @@ struct device {
275 290
276 struct kobject kobj; 291 struct kobject kobj;
277 char bus_id[BUS_ID_SIZE]; /* position on parent bus */ 292 char bus_id[BUS_ID_SIZE]; /* position on parent bus */
293 struct device_attribute uevent_attr;
278 294
279 struct semaphore sem; /* semaphore to synchronize calls to 295 struct semaphore sem; /* semaphore to synchronize calls to
280 * its driver. 296 * its driver.
@@ -343,23 +359,6 @@ extern int device_attach(struct device * dev);
343extern void driver_attach(struct device_driver * drv); 359extern void driver_attach(struct device_driver * drv);
344 360
345 361
346/* driverfs interface for exporting device attributes */
347
348struct device_attribute {
349 struct attribute attr;
350 ssize_t (*show)(struct device *dev, struct device_attribute *attr,
351 char *buf);
352 ssize_t (*store)(struct device *dev, struct device_attribute *attr,
353 const char *buf, size_t count);
354};
355
356#define DEVICE_ATTR(_name,_mode,_show,_store) \
357struct device_attribute dev_attr_##_name = __ATTR(_name,_mode,_show,_store)
358
359
360extern int device_create_file(struct device *device, struct device_attribute * entry);
361extern void device_remove_file(struct device * dev, struct device_attribute * attr);
362
363/* 362/*
364 * Platform "fixup" functions - allow the platform to have their say 363 * Platform "fixup" functions - allow the platform to have their say
365 * about devices and actions that the general device layer doesn't 364 * about devices and actions that the general device layer doesn't
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 01796c41c951..78af34840c69 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -132,6 +132,7 @@ struct gendisk {
132struct disk_attribute { 132struct disk_attribute {
133 struct attribute attr; 133 struct attribute attr;
134 ssize_t (*show)(struct gendisk *, char *); 134 ssize_t (*show)(struct gendisk *, char *);
135 ssize_t (*store)(struct gendisk *, const char *, size_t);
135}; 136};
136 137
137/* 138/*