diff options
-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); |
206 | return ret; | ||
207 | } | ||
208 | static ssize_t | ||
209 | part_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 | ||
208 | static struct sysfs_ops part_sysfs_ops = { | 221 | static 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 | ||
226 | static 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 | } | ||
212 | static ssize_t part_dev_read(struct hd_struct * p, char *page) | 232 | static 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 | } |
252 | static struct part_attribute part_attr_uevent = { | ||
253 | .attr = {.name = "uevent", .mode = S_IWUSR }, | ||
254 | .store = part_uevent_store | ||
255 | }; | ||
232 | static struct part_attribute part_attr_dev = { | 256 | static 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 | ||
249 | static struct attribute * default_attrs[] = { | 273 | static 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) | |||
190 | extern int class_create_file(struct class *, const struct class_attribute *); | 190 | extern int class_create_file(struct class *, const struct class_attribute *); |
191 | extern void class_remove_file(struct class *, const struct class_attribute *); | 191 | extern void class_remove_file(struct class *, const struct class_attribute *); |
192 | 192 | ||
193 | struct 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) \ | ||
200 | struct class_device_attribute class_device_attr_##_name = \ | ||
201 | __ATTR(_name,_mode,_show,_store) | ||
202 | |||
203 | extern int class_device_create_file(struct class_device *, | ||
204 | const struct class_device_attribute *); | ||
193 | 205 | ||
194 | struct class_device { | 206 | struct 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 *); | |||
228 | extern struct class_device * class_device_get(struct class_device *); | 241 | extern struct class_device * class_device_get(struct class_device *); |
229 | extern void class_device_put(struct class_device *); | 242 | extern void class_device_put(struct class_device *); |
230 | 243 | ||
231 | struct 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) \ | ||
238 | struct class_device_attribute class_device_attr_##_name = \ | ||
239 | __ATTR(_name,_mode,_show,_store) | ||
240 | |||
241 | extern int class_device_create_file(struct class_device *, | ||
242 | const struct class_device_attribute *); | ||
243 | extern void class_device_remove_file(struct class_device *, | 244 | extern void class_device_remove_file(struct class_device *, |
244 | const struct class_device_attribute *); | 245 | const struct class_device_attribute *); |
245 | extern int class_device_create_bin_file(struct class_device *, | 246 | extern 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, | |||
266 | extern void class_device_destroy(struct class *cls, dev_t devt); | 267 | extern void class_device_destroy(struct class *cls, dev_t devt); |
267 | 268 | ||
268 | 269 | ||
270 | /* interface for exporting device attributes */ | ||
271 | struct 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) \ | ||
280 | struct device_attribute dev_attr_##_name = __ATTR(_name,_mode,_show,_store) | ||
281 | |||
282 | extern int device_create_file(struct device *device, struct device_attribute * entry); | ||
283 | extern void device_remove_file(struct device * dev, struct device_attribute * attr); | ||
269 | struct device { | 284 | struct 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); | |||
343 | extern void driver_attach(struct device_driver * drv); | 359 | extern void driver_attach(struct device_driver * drv); |
344 | 360 | ||
345 | 361 | ||
346 | /* driverfs interface for exporting device attributes */ | ||
347 | |||
348 | struct 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) \ | ||
357 | struct device_attribute dev_attr_##_name = __ATTR(_name,_mode,_show,_store) | ||
358 | |||
359 | |||
360 | extern int device_create_file(struct device *device, struct device_attribute * entry); | ||
361 | extern 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 { | |||
132 | struct disk_attribute { | 132 | struct 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 | /* |