diff options
Diffstat (limited to 'block/genhd.c')
| -rw-r--r-- | block/genhd.c | 33 |
1 files changed, 32 insertions, 1 deletions
diff --git a/block/genhd.c b/block/genhd.c index 93a2cf654597..863a8c0623ed 100644 --- a/block/genhd.c +++ b/block/genhd.c | |||
| @@ -423,7 +423,10 @@ static ssize_t disk_size_read(struct gendisk * disk, char *page) | |||
| 423 | { | 423 | { |
| 424 | return sprintf(page, "%llu\n", (unsigned long long)get_capacity(disk)); | 424 | return sprintf(page, "%llu\n", (unsigned long long)get_capacity(disk)); |
| 425 | } | 425 | } |
| 426 | 426 | static ssize_t disk_capability_read(struct gendisk *disk, char *page) | |
| 427 | { | ||
| 428 | return sprintf(page, "%x\n", disk->flags); | ||
| 429 | } | ||
| 427 | static ssize_t disk_stats_read(struct gendisk * disk, char *page) | 430 | static ssize_t disk_stats_read(struct gendisk * disk, char *page) |
| 428 | { | 431 | { |
| 429 | preempt_disable(); | 432 | preempt_disable(); |
| @@ -466,6 +469,10 @@ static struct disk_attribute disk_attr_size = { | |||
| 466 | .attr = {.name = "size", .mode = S_IRUGO }, | 469 | .attr = {.name = "size", .mode = S_IRUGO }, |
| 467 | .show = disk_size_read | 470 | .show = disk_size_read |
| 468 | }; | 471 | }; |
| 472 | static struct disk_attribute disk_attr_capability = { | ||
| 473 | .attr = {.name = "capability", .mode = S_IRUGO }, | ||
| 474 | .show = disk_capability_read | ||
| 475 | }; | ||
| 469 | static struct disk_attribute disk_attr_stat = { | 476 | static struct disk_attribute disk_attr_stat = { |
| 470 | .attr = {.name = "stat", .mode = S_IRUGO }, | 477 | .attr = {.name = "stat", .mode = S_IRUGO }, |
| 471 | .show = disk_stats_read | 478 | .show = disk_stats_read |
| @@ -506,6 +513,7 @@ static struct attribute * default_attrs[] = { | |||
| 506 | &disk_attr_removable.attr, | 513 | &disk_attr_removable.attr, |
| 507 | &disk_attr_size.attr, | 514 | &disk_attr_size.attr, |
| 508 | &disk_attr_stat.attr, | 515 | &disk_attr_stat.attr, |
| 516 | &disk_attr_capability.attr, | ||
| 509 | #ifdef CONFIG_FAIL_MAKE_REQUEST | 517 | #ifdef CONFIG_FAIL_MAKE_REQUEST |
| 510 | &disk_attr_fail.attr, | 518 | &disk_attr_fail.attr, |
| 511 | #endif | 519 | #endif |
| @@ -688,6 +696,27 @@ struct seq_operations diskstats_op = { | |||
| 688 | .show = diskstats_show | 696 | .show = diskstats_show |
| 689 | }; | 697 | }; |
| 690 | 698 | ||
| 699 | static void media_change_notify_thread(struct work_struct *work) | ||
| 700 | { | ||
| 701 | struct gendisk *gd = container_of(work, struct gendisk, async_notify); | ||
| 702 | char event[] = "MEDIA_CHANGE=1"; | ||
| 703 | char *envp[] = { event, NULL }; | ||
| 704 | |||
| 705 | /* | ||
| 706 | * set enviroment vars to indicate which event this is for | ||
| 707 | * so that user space will know to go check the media status. | ||
| 708 | */ | ||
| 709 | kobject_uevent_env(&gd->kobj, KOBJ_CHANGE, envp); | ||
| 710 | put_device(gd->driverfs_dev); | ||
| 711 | } | ||
| 712 | |||
| 713 | void genhd_media_change_notify(struct gendisk *disk) | ||
| 714 | { | ||
| 715 | get_device(disk->driverfs_dev); | ||
| 716 | schedule_work(&disk->async_notify); | ||
| 717 | } | ||
| 718 | EXPORT_SYMBOL_GPL(genhd_media_change_notify); | ||
| 719 | |||
| 691 | struct gendisk *alloc_disk(int minors) | 720 | struct gendisk *alloc_disk(int minors) |
| 692 | { | 721 | { |
| 693 | return alloc_disk_node(minors, -1); | 722 | return alloc_disk_node(minors, -1); |
| @@ -717,6 +746,8 @@ struct gendisk *alloc_disk_node(int minors, int node_id) | |||
| 717 | kobj_set_kset_s(disk,block_subsys); | 746 | kobj_set_kset_s(disk,block_subsys); |
| 718 | kobject_init(&disk->kobj); | 747 | kobject_init(&disk->kobj); |
| 719 | rand_initialize_disk(disk); | 748 | rand_initialize_disk(disk); |
| 749 | INIT_WORK(&disk->async_notify, | ||
| 750 | media_change_notify_thread); | ||
| 720 | } | 751 | } |
| 721 | return disk; | 752 | return disk; |
| 722 | } | 753 | } |
