X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=block%2Fgenhd.c;h=f2ac914160d1a96e7258bd86949caef3dcdec6a3;hb=7607341a265a56cdf8b4bf10d355098e80ea481b;hp=93a2cf654597c25502da7fb128745c11c01581c9;hpb=31f6e1bd3b58c9a67e5ea0c2d372fbf5fc9e326d;p=linux-2.6 diff --git a/block/genhd.c b/block/genhd.c index 93a2cf6545..f2ac914160 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -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); @@ -423,7 +419,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 +465,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 +509,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 @@ -536,61 +540,42 @@ static int block_uevent_filter(struct kset *kset, struct kobject *kobj) return ((ktype == &ktype_block) || (ktype == &ktype_part)); } -static int block_uevent(struct kset *kset, struct kobject *kobj, char **envp, - int num_envp, char *buffer, int buffer_size) +static int block_uevent(struct kset *kset, struct kobject *kobj, + struct kobj_uevent_env *env) { struct kobj_type *ktype = get_ktype(kobj); struct device *physdev; struct gendisk *disk; struct hd_struct *part; - int length = 0; - int i = 0; if (ktype == &ktype_block) { disk = container_of(kobj, struct gendisk, kobj); - add_uevent_var(envp, num_envp, &i, buffer, buffer_size, - &length, "MINOR=%u", disk->first_minor); + add_uevent_var(env, "MINOR=%u", disk->first_minor); } else if (ktype == &ktype_part) { disk = container_of(kobj->parent, struct gendisk, kobj); part = container_of(kobj, struct hd_struct, kobj); - add_uevent_var(envp, num_envp, &i, buffer, buffer_size, - &length, "MINOR=%u", + add_uevent_var(env, "MINOR=%u", disk->first_minor + part->partno); } else return 0; - add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, - "MAJOR=%u", disk->major); + add_uevent_var(env, "MAJOR=%u", disk->major); /* add physical device, backing this device */ physdev = disk->driverfs_dev; if (physdev) { char *path = kobject_get_path(&physdev->kobj, GFP_KERNEL); - add_uevent_var(envp, num_envp, &i, buffer, buffer_size, - &length, "PHYSDEVPATH=%s", path); + add_uevent_var(env, "PHYSDEVPATH=%s", path); kfree(path); if (physdev->bus) - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PHYSDEVBUS=%s", - physdev->bus->name); + add_uevent_var(env, "PHYSDEVBUS=%s", physdev->bus->name); if (physdev->driver) - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PHYSDEVDRIVER=%s", - physdev->driver->name); + add_uevent_var(env, physdev->driver->name); } - /* terminate, set to next free slot, shrink available space */ - envp[i] = NULL; - envp = &envp[i]; - num_envp -= i; - buffer = &buffer[length]; - buffer_size -= length; - return 0; } @@ -688,6 +673,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); @@ -697,26 +703,29 @@ 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) { + free_disk_stats(disk); 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; }