Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/cpufreq
[sfrench/cifs-2.6.git] / block / genhd.c
index 93a2cf654597c25502da7fb128745c11c01581c9..863a8c0623ed824e27d85f32a52cf10ea39d1c02 100644 (file)
@@ -423,7 +423,10 @@ static ssize_t disk_size_read(struct gendisk * disk, char *page)
 {
        return sprintf(page, "%llu\n", (unsigned long long)get_capacity(disk));
 }
-
+static ssize_t disk_capability_read(struct gendisk *disk, char *page)
+{
+       return sprintf(page, "%x\n", disk->flags);
+}
 static ssize_t disk_stats_read(struct gendisk * disk, char *page)
 {
        preempt_disable();
@@ -466,6 +469,10 @@ static struct disk_attribute disk_attr_size = {
        .attr = {.name = "size", .mode = S_IRUGO },
        .show   = disk_size_read
 };
+static struct disk_attribute disk_attr_capability = {
+       .attr = {.name = "capability", .mode = S_IRUGO },
+       .show   = disk_capability_read
+};
 static struct disk_attribute disk_attr_stat = {
        .attr = {.name = "stat", .mode = S_IRUGO },
        .show   = disk_stats_read
@@ -506,6 +513,7 @@ static struct attribute * default_attrs[] = {
        &disk_attr_removable.attr,
        &disk_attr_size.attr,
        &disk_attr_stat.attr,
+       &disk_attr_capability.attr,
 #ifdef CONFIG_FAIL_MAKE_REQUEST
        &disk_attr_fail.attr,
 #endif
@@ -688,6 +696,27 @@ struct seq_operations diskstats_op = {
        .show   = diskstats_show
 };
 
+static void media_change_notify_thread(struct work_struct *work)
+{
+       struct gendisk *gd = container_of(work, struct gendisk, async_notify);
+       char event[] = "MEDIA_CHANGE=1";
+       char *envp[] = { event, NULL };
+
+       /*
+        * set enviroment vars to indicate which event this is for
+        * so that user space will know to go check the media status.
+        */
+       kobject_uevent_env(&gd->kobj, KOBJ_CHANGE, envp);
+       put_device(gd->driverfs_dev);
+}
+
+void genhd_media_change_notify(struct gendisk *disk)
+{
+       get_device(disk->driverfs_dev);
+       schedule_work(&disk->async_notify);
+}
+EXPORT_SYMBOL_GPL(genhd_media_change_notify);
+
 struct gendisk *alloc_disk(int minors)
 {
        return alloc_disk_node(minors, -1);
@@ -717,6 +746,8 @@ struct gendisk *alloc_disk_node(int minors, int node_id)
                kobj_set_kset_s(disk,block_subsys);
                kobject_init(&disk->kobj);
                rand_initialize_disk(disk);
+               INIT_WORK(&disk->async_notify,
+                       media_change_notify_thread);
        }
        return disk;
 }