X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fpartitions%2Fcheck.c;h=3d73d94d93a7dd9321cdfe5d9750fcf25a836df5;hb=refs%2Fheads%2Fvserver;hp=7ef1f094de911998a88fe76bda393f136d60ec3c;hpb=43bc926fffd92024b46cafaf7350d669ba9ca884;p=linux-2.6.git diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 7ef1f094d..3d73d94d9 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -18,10 +18,8 @@ #include #include #include -#include #include "check.h" -#include "devfs.h" #include "acorn.h" #include "amiga.h" @@ -155,38 +153,42 @@ static struct parsed_partitions * check_partition(struct gendisk *hd, struct block_device *bdev) { struct parsed_partitions *state; - int i, res; + int i, res, err; state = kmalloc(sizeof(struct parsed_partitions), GFP_KERNEL); if (!state) return NULL; -#ifdef CONFIG_DEVFS_FS - if (hd->devfs_name[0] != '\0') { - printk(KERN_INFO " /dev/%s:", hd->devfs_name); + disk_name(hd, 0, state->name); + printk(KERN_INFO " %s:", state->name); + if (isdigit(state->name[strlen(state->name)-1])) sprintf(state->name, "p"); - } -#endif - else { - disk_name(hd, 0, state->name); - printk(KERN_INFO " %s:", state->name); - if (isdigit(state->name[strlen(state->name)-1])) - sprintf(state->name, "p"); - } + state->limit = hd->minors; - i = res = 0; + i = res = err = 0; while (!res && check_part[i]) { memset(&state->parts, 0, sizeof(state->parts)); res = check_part[i++](state, bdev); + if (res < 0) { + /* We have hit an I/O error which we don't report now. + * But record it, and let the others do their job. + */ + err = res; + res = 0; + } + } if (res > 0) return state; + if (!err) + /* The partition is unrecognized. So report I/O errors if there were any */ + res = err; if (!res) printk(" unknown partition table\n"); else if (warn_no_part) printk(" unable to read partition table\n"); kfree(state); - return NULL; + return ERR_PTR(res); } /* @@ -274,12 +276,39 @@ static struct part_attribute part_attr_stat = { .show = part_stat_read }; +#ifdef CONFIG_FAIL_MAKE_REQUEST + +static ssize_t part_fail_store(struct hd_struct * p, + const char *buf, size_t count) +{ + int i; + + if (count > 0 && sscanf(buf, "%d", &i) > 0) + p->make_it_fail = (i == 0) ? 0 : 1; + + return count; +} +static ssize_t part_fail_read(struct hd_struct * p, char *page) +{ + return sprintf(page, "%d\n", p->make_it_fail); +} +static struct part_attribute part_attr_fail = { + .attr = {.name = "make-it-fail", .mode = S_IRUGO | S_IWUSR }, + .store = part_fail_store, + .show = part_fail_read +}; + +#endif + static struct attribute * default_attrs[] = { &part_attr_uevent.attr, &part_attr_dev.attr, &part_attr_start.attr, &part_attr_size.attr, &part_attr_stat.attr, +#ifdef CONFIG_FAIL_MAKE_REQUEST + &part_attr_fail.attr, +#endif NULL, }; @@ -328,7 +357,7 @@ void delete_partition(struct gendisk *disk, int part) p->nr_sects = 0; p->ios[0] = p->ios[1] = 0; p->sectors[0] = p->sectors[1] = 0; - devfs_remove("%s/part%d", disk->devfs_name, part); + sysfs_remove_link(&p->kobj, "subsystem"); if (p->holder_dir) kobject_unregister(p->holder_dir); kobject_uevent(&p->kobj, KOBJ_REMOVE); @@ -348,10 +377,7 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len) p->start_sect = start; p->nr_sects = len; p->partno = part; - - devfs_mk_bdev(MKDEV(disk->major, disk->first_minor + part), - S_IFBLK|S_IRUSR|S_IWUSR, - "%s/part%d", disk->devfs_name, part); + p->policy = disk->policy; if (isdigit(disk->kobj.name[strlen(disk->kobj.name)-1])) snprintf(p->kobj.name,KOBJ_NAME_LEN,"%sp%d",disk->kobj.name,part); @@ -363,6 +389,7 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len) kobject_add(&p->kobj); if (!disk->part_uevent_suppress) kobject_uevent(&p->kobj, KOBJ_ADD); + sysfs_create_link(&p->kobj, &block_subsys.kset.kobj, "subsystem"); partition_sysfs_add_subdir(p); disk->part[part-1] = p; } @@ -387,17 +414,48 @@ static char *make_block_name(struct gendisk *disk) return name; } -static void disk_sysfs_symlinks(struct gendisk *disk) +static int disk_sysfs_symlinks(struct gendisk *disk) { struct device *target = get_device(disk->driverfs_dev); + int err; + char *disk_name = NULL; + if (target) { - char *disk_name = make_block_name(disk); - sysfs_create_link(&disk->kobj,&target->kobj,"device"); - if (disk_name) { - sysfs_create_link(&target->kobj,&disk->kobj,disk_name); - kfree(disk_name); + disk_name = make_block_name(disk); + if (!disk_name) { + err = -ENOMEM; + goto err_out; } + + err = sysfs_create_link(&disk->kobj, &target->kobj, "device"); + if (err) + goto err_out_disk_name; + + err = sysfs_create_link(&target->kobj, &disk->kobj, disk_name); + if (err) + goto err_out_dev_link; } + + err = sysfs_create_link(&disk->kobj, &block_subsys.kset.kobj, + "subsystem"); + if (err) + goto err_out_disk_name_lnk; + + kfree(disk_name); + + return 0; + +err_out_disk_name_lnk: + if (target) { + sysfs_remove_link(&target->kobj, disk_name); +err_out_dev_link: + sysfs_remove_link(&disk->kobj, "device"); +err_out_disk_name: + kfree(disk_name); +err_out: + put_device(target); + } + return err; } /* Not exported, helper to add_disk(). */ @@ -416,18 +474,16 @@ void register_disk(struct gendisk *disk) *s = '!'; if ((err = kobject_add(&disk->kobj))) return; - disk_sysfs_symlinks(disk); + err = disk_sysfs_symlinks(disk); + if (err) { + kobject_del(&disk->kobj); + return; + } disk_sysfs_add_subdirs(disk); /* No minors to use for partitions */ - if (disk->minors == 1) { - if (disk->devfs_name[0] != '\0') - devfs_add_disk(disk); + if (disk->minors == 1) goto exit; - } - - /* always add handle for the whole disk */ - devfs_add_partitioned(disk); /* No such device (e.g., media were just removed) */ if (!get_capacity(disk)) @@ -476,11 +532,17 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev) disk->fops->revalidate_disk(disk); if (!get_capacity(disk) || !(state = check_partition(disk, bdev))) return 0; + if (IS_ERR(state)) /* I/O error reading the partition table */ + return PTR_ERR(state); for (p = 1; p < state->limit; p++) { sector_t size = state->parts[p].size; sector_t from = state->parts[p].from; if (!size) continue; + if (from + size > get_capacity(disk)) { + printk(" %s: p%d exceeds device capacity\n", + disk->disk_name, p); + } add_partition(disk, p, from, size); #ifdef CONFIG_BLK_DEV_MD if (state->parts[p].flags) @@ -496,8 +558,8 @@ unsigned char *read_dev_sector(struct block_device *bdev, sector_t n, Sector *p) struct address_space *mapping = bdev->bd_inode->i_mapping; struct page *page; - page = read_cache_page(mapping, (pgoff_t)(n >> (PAGE_CACHE_SHIFT-9)), - (filler_t *)mapping->a_ops->readpage, NULL); + page = read_mapping_page(mapping, (pgoff_t)(n >> (PAGE_CACHE_SHIFT-9)), + NULL); if (!IS_ERR(page)) { wait_on_page_locked(page); if (!PageUptodate(page)) @@ -531,8 +593,6 @@ void del_gendisk(struct gendisk *disk) disk_stat_set_all(disk, 0); disk->stamp = 0; - devfs_remove_disk(disk); - kobject_uevent(&disk->kobj, KOBJ_REMOVE); if (disk->holder_dir) kobject_unregister(disk->holder_dir); @@ -548,5 +608,6 @@ void del_gendisk(struct gendisk *disk) put_device(disk->driverfs_dev); disk->driverfs_dev = NULL; } + sysfs_remove_link(&disk->kobj, "subsystem"); kobject_del(&disk->kobj); }