Merge branch 'linus' of master.kernel.org:/pub/scm/linux/kernel/git/perex/alsa
[powerpc.git] / block / genhd.c
index 7efa8bb..3af1e7a 100644 (file)
@@ -108,28 +108,24 @@ out:
 
 EXPORT_SYMBOL(register_blkdev);
 
-/* todo: make void - error printk here */
-int unregister_blkdev(unsigned int major, const char *name)
+void unregister_blkdev(unsigned int major, const char *name)
 {
        struct blk_major_name **n;
        struct blk_major_name *p = NULL;
        int index = major_to_index(major);
-       int ret = 0;
 
        mutex_lock(&block_subsys_lock);
        for (n = &major_names[index]; *n; n = &(*n)->next)
                if ((*n)->major == major)
                        break;
-       if (!*n || strcmp((*n)->name, name))
-               ret = -EINVAL;
-       else {
+       if (!*n || strcmp((*n)->name, name)) {
+               WARN_ON(1);
+       else {
                p = *n;
                *n = p->next;
        }
        mutex_unlock(&block_subsys_lock);
        kfree(p);
-
-       return ret;
 }
 
 EXPORT_SYMBOL(unregister_blkdev);
@@ -696,6 +692,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);
@@ -705,26 +722,28 @@ struct gendisk *alloc_disk_node(int minors, int node_id)
 {
        struct gendisk *disk;
 
-       disk = kmalloc_node(sizeof(struct gendisk), GFP_KERNEL, node_id);
+       disk = kmalloc_node(sizeof(struct gendisk),
+                               GFP_KERNEL | __GFP_ZERO, node_id);
        if (disk) {
-               memset(disk, 0, sizeof(struct gendisk));
                if (!init_disk_stats(disk)) {
                        kfree(disk);
                        return NULL;
                }
                if (minors > 1) {
                        int size = (minors - 1) * sizeof(struct hd_struct *);
-                       disk->part = kmalloc_node(size, GFP_KERNEL, node_id);
+                       disk->part = kmalloc_node(size,
+                               GFP_KERNEL | __GFP_ZERO, node_id);
                        if (!disk->part) {
                                kfree(disk);
                                return NULL;
                        }
-                       memset(disk->part, 0, size);
                }
                disk->minors = minors;
                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;
 }