diff options
Diffstat (limited to 'fs/partitions/check.c')
-rw-r--r-- | fs/partitions/check.c | 46 |
1 files changed, 43 insertions, 3 deletions
diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 6fb4b6150d7..3d73d94d93a 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -153,7 +153,7 @@ 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) @@ -165,19 +165,30 @@ check_partition(struct gendisk *hd, struct block_device *bdev) 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); } /* @@ -265,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, }; @@ -494,6 +532,8 @@ 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; |