diff --git a/[refs] b/[refs] index 44a4994c5fbf..bdf530d3f73b 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: f94d4fe0b5bbe8385245a1d9ef11d785c05df0da +refs/heads/master: 41d82bdb40af74a88cff4589ea7a60091b11070e diff --git a/trunk/Documentation/device-mapper/dm-raid.txt b/trunk/Documentation/device-mapper/dm-raid.txt index 56fb62b09fc5..728c38c242d6 100644 --- a/trunk/Documentation/device-mapper/dm-raid.txt +++ b/trunk/Documentation/device-mapper/dm-raid.txt @@ -141,4 +141,3 @@ Version History 1.2.0 Handle creation of arrays that contain failed devices. 1.3.0 Added support for RAID 10 1.3.1 Allow device replacement/rebuild for RAID 10 -1.3.2 Fix/improve redundancy checking for RAID10 diff --git a/trunk/arch/powerpc/kernel/entry_32.S b/trunk/arch/powerpc/kernel/entry_32.S index d22e73e4618b..e514de57a125 100644 --- a/trunk/arch/powerpc/kernel/entry_32.S +++ b/trunk/arch/powerpc/kernel/entry_32.S @@ -439,6 +439,8 @@ ret_from_fork: ret_from_kernel_thread: REST_NVGPRS(r1) bl schedule_tail + li r3,0 + stw r3,0(r1) mtlr r14 mr r3,r15 PPC440EP_ERR42 diff --git a/trunk/drivers/md/dm-raid.c b/trunk/drivers/md/dm-raid.c index 9e58dbd8d8cb..3d8984edeff7 100644 --- a/trunk/drivers/md/dm-raid.c +++ b/trunk/drivers/md/dm-raid.c @@ -340,22 +340,24 @@ static int validate_region_size(struct raid_set *rs, unsigned long region_size) } /* - * validate_raid_redundancy + * validate_rebuild_devices * @rs * - * Determine if there are enough devices in the array that haven't - * failed (or are being rebuilt) to form a usable array. + * Determine if the devices specified for rebuild can result in a valid + * usable array that is capable of rebuilding the given devices. * * Returns: 0 on success, -EINVAL on failure. */ -static int validate_raid_redundancy(struct raid_set *rs) +static int validate_rebuild_devices(struct raid_set *rs) { unsigned i, rebuild_cnt = 0; unsigned rebuilds_per_group, copies, d; + if (!(rs->print_flags & DMPF_REBUILD)) + return 0; + for (i = 0; i < rs->md.raid_disks; i++) - if (!test_bit(In_sync, &rs->dev[i].rdev.flags) || - !rs->dev[i].rdev.sb_page) + if (!test_bit(In_sync, &rs->dev[i].rdev.flags)) rebuild_cnt++; switch (rs->raid_type->level) { @@ -391,24 +393,27 @@ static int validate_raid_redundancy(struct raid_set *rs) * A A B B C * C D D E E */ + rebuilds_per_group = 0; for (i = 0; i < rs->md.raid_disks * copies; i++) { - if (!(i % copies)) - rebuilds_per_group = 0; d = i % rs->md.raid_disks; - if ((!rs->dev[d].rdev.sb_page || - !test_bit(In_sync, &rs->dev[d].rdev.flags)) && + if (!test_bit(In_sync, &rs->dev[d].rdev.flags) && (++rebuilds_per_group >= copies)) goto too_many; + if (!((i + 1) % copies)) + rebuilds_per_group = 0; } break; default: - if (rebuild_cnt) - return -EINVAL; + DMERR("The rebuild parameter is not supported for %s", + rs->raid_type->name); + rs->ti->error = "Rebuild not supported for this RAID type"; + return -EINVAL; } return 0; too_many: + rs->ti->error = "Too many rebuild devices specified"; return -EINVAL; } @@ -659,6 +664,9 @@ static int parse_raid_params(struct raid_set *rs, char **argv, } rs->md.dev_sectors = sectors_per_dev; + if (validate_rebuild_devices(rs)) + return -EINVAL; + /* Assume there are no metadata devices until the drives are parsed */ rs->md.persistent = 0; rs->md.external = 1; @@ -987,10 +995,28 @@ static int super_validate(struct mddev *mddev, struct md_rdev *rdev) static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs) { int ret; + unsigned redundancy = 0; struct raid_dev *dev; struct md_rdev *rdev, *tmp, *freshest; struct mddev *mddev = &rs->md; + switch (rs->raid_type->level) { + case 1: + redundancy = rs->md.raid_disks - 1; + break; + case 4: + case 5: + case 6: + redundancy = rs->raid_type->parity_devs; + break; + case 10: + redundancy = raid10_md_layout_to_copies(mddev->layout) - 1; + break; + default: + ti->error = "Unknown RAID type"; + return -EINVAL; + } + freshest = NULL; rdev_for_each_safe(rdev, tmp, mddev) { /* @@ -1019,43 +1045,44 @@ static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs) break; default: dev = container_of(rdev, struct raid_dev, rdev); - if (dev->meta_dev) - dm_put_device(ti, dev->meta_dev); + if (redundancy--) { + if (dev->meta_dev) + dm_put_device(ti, dev->meta_dev); - dev->meta_dev = NULL; - rdev->meta_bdev = NULL; + dev->meta_dev = NULL; + rdev->meta_bdev = NULL; - if (rdev->sb_page) - put_page(rdev->sb_page); + if (rdev->sb_page) + put_page(rdev->sb_page); - rdev->sb_page = NULL; + rdev->sb_page = NULL; - rdev->sb_loaded = 0; + rdev->sb_loaded = 0; - /* - * We might be able to salvage the data device - * even though the meta device has failed. For - * now, we behave as though '- -' had been - * set for this device in the table. - */ - if (dev->data_dev) - dm_put_device(ti, dev->data_dev); + /* + * We might be able to salvage the data device + * even though the meta device has failed. For + * now, we behave as though '- -' had been + * set for this device in the table. + */ + if (dev->data_dev) + dm_put_device(ti, dev->data_dev); + + dev->data_dev = NULL; + rdev->bdev = NULL; - dev->data_dev = NULL; - rdev->bdev = NULL; + list_del(&rdev->same_set); - list_del(&rdev->same_set); + continue; + } + ti->error = "Failed to load superblock"; + return ret; } } if (!freshest) return 0; - if (validate_raid_redundancy(rs)) { - rs->ti->error = "Insufficient redundancy to activate array"; - return -EINVAL; - } - /* * Validation of the freshest device provides the source of * validation for the remaining devices. @@ -1405,7 +1432,7 @@ static void raid_resume(struct dm_target *ti) static struct target_type raid_target = { .name = "raid", - .version = {1, 4, 1}, + .version = {1, 4, 0}, .module = THIS_MODULE, .ctr = raid_ctr, .dtr = raid_dtr,