diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-01-28 18:15:34 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-01-28 18:15:34 -0500 |
commit | f94d4fe0b5bbe8385245a1d9ef11d785c05df0da (patch) | |
tree | 64e20ce42b24bb5f47bdbde3eff4ab55f6e9f89d /drivers | |
parent | 45e72af09faa7dad5d8539ebac0fe317ae88318b (diff) | |
parent | 55ebbb59c1c6eb1b040f62b8c4ae0b724de6e55a (diff) |
Merge tag 'md-3.8-fixes' of git://neil.brown.name/md
Pull dmraid fix from NeilBrown:
"Just one fix for md in 3.8
dmraid assess redundancy and replacements slightly inaccurately which
could lead to some degraded arrays failing to assemble."
* tag 'md-3.8-fixes' of git://neil.brown.name/md:
DM-RAID: Fix RAID10's check for sufficient redundancy
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/md/dm-raid.c | 101 |
1 files changed, 37 insertions, 64 deletions
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index 3d8984edeff7..9e58dbd8d8cb 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c | |||
@@ -340,24 +340,22 @@ static int validate_region_size(struct raid_set *rs, unsigned long region_size) | |||
340 | } | 340 | } |
341 | 341 | ||
342 | /* | 342 | /* |
343 | * validate_rebuild_devices | 343 | * validate_raid_redundancy |
344 | * @rs | 344 | * @rs |
345 | * | 345 | * |
346 | * Determine if the devices specified for rebuild can result in a valid | 346 | * Determine if there are enough devices in the array that haven't |
347 | * usable array that is capable of rebuilding the given devices. | 347 | * failed (or are being rebuilt) to form a usable array. |
348 | * | 348 | * |
349 | * Returns: 0 on success, -EINVAL on failure. | 349 | * Returns: 0 on success, -EINVAL on failure. |
350 | */ | 350 | */ |
351 | static int validate_rebuild_devices(struct raid_set *rs) | 351 | static int validate_raid_redundancy(struct raid_set *rs) |
352 | { | 352 | { |
353 | unsigned i, rebuild_cnt = 0; | 353 | unsigned i, rebuild_cnt = 0; |
354 | unsigned rebuilds_per_group, copies, d; | 354 | unsigned rebuilds_per_group, copies, d; |
355 | 355 | ||
356 | if (!(rs->print_flags & DMPF_REBUILD)) | ||
357 | return 0; | ||
358 | |||
359 | for (i = 0; i < rs->md.raid_disks; i++) | 356 | for (i = 0; i < rs->md.raid_disks; i++) |
360 | if (!test_bit(In_sync, &rs->dev[i].rdev.flags)) | 357 | if (!test_bit(In_sync, &rs->dev[i].rdev.flags) || |
358 | !rs->dev[i].rdev.sb_page) | ||
361 | rebuild_cnt++; | 359 | rebuild_cnt++; |
362 | 360 | ||
363 | switch (rs->raid_type->level) { | 361 | switch (rs->raid_type->level) { |
@@ -393,27 +391,24 @@ static int validate_rebuild_devices(struct raid_set *rs) | |||
393 | * A A B B C | 391 | * A A B B C |
394 | * C D D E E | 392 | * C D D E E |
395 | */ | 393 | */ |
396 | rebuilds_per_group = 0; | ||
397 | for (i = 0; i < rs->md.raid_disks * copies; i++) { | 394 | for (i = 0; i < rs->md.raid_disks * copies; i++) { |
395 | if (!(i % copies)) | ||
396 | rebuilds_per_group = 0; | ||
398 | d = i % rs->md.raid_disks; | 397 | d = i % rs->md.raid_disks; |
399 | if (!test_bit(In_sync, &rs->dev[d].rdev.flags) && | 398 | if ((!rs->dev[d].rdev.sb_page || |
399 | !test_bit(In_sync, &rs->dev[d].rdev.flags)) && | ||
400 | (++rebuilds_per_group >= copies)) | 400 | (++rebuilds_per_group >= copies)) |
401 | goto too_many; | 401 | goto too_many; |
402 | if (!((i + 1) % copies)) | ||
403 | rebuilds_per_group = 0; | ||
404 | } | 402 | } |
405 | break; | 403 | break; |
406 | default: | 404 | default: |
407 | DMERR("The rebuild parameter is not supported for %s", | 405 | if (rebuild_cnt) |
408 | rs->raid_type->name); | 406 | return -EINVAL; |
409 | rs->ti->error = "Rebuild not supported for this RAID type"; | ||
410 | return -EINVAL; | ||
411 | } | 407 | } |
412 | 408 | ||
413 | return 0; | 409 | return 0; |
414 | 410 | ||
415 | too_many: | 411 | too_many: |
416 | rs->ti->error = "Too many rebuild devices specified"; | ||
417 | return -EINVAL; | 412 | return -EINVAL; |
418 | } | 413 | } |
419 | 414 | ||
@@ -664,9 +659,6 @@ static int parse_raid_params(struct raid_set *rs, char **argv, | |||
664 | } | 659 | } |
665 | rs->md.dev_sectors = sectors_per_dev; | 660 | rs->md.dev_sectors = sectors_per_dev; |
666 | 661 | ||
667 | if (validate_rebuild_devices(rs)) | ||
668 | return -EINVAL; | ||
669 | |||
670 | /* Assume there are no metadata devices until the drives are parsed */ | 662 | /* Assume there are no metadata devices until the drives are parsed */ |
671 | rs->md.persistent = 0; | 663 | rs->md.persistent = 0; |
672 | rs->md.external = 1; | 664 | rs->md.external = 1; |
@@ -995,28 +987,10 @@ static int super_validate(struct mddev *mddev, struct md_rdev *rdev) | |||
995 | static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs) | 987 | static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs) |
996 | { | 988 | { |
997 | int ret; | 989 | int ret; |
998 | unsigned redundancy = 0; | ||
999 | struct raid_dev *dev; | 990 | struct raid_dev *dev; |
1000 | struct md_rdev *rdev, *tmp, *freshest; | 991 | struct md_rdev *rdev, *tmp, *freshest; |
1001 | struct mddev *mddev = &rs->md; | 992 | struct mddev *mddev = &rs->md; |
1002 | 993 | ||
1003 | switch (rs->raid_type->level) { | ||
1004 | case 1: | ||
1005 | redundancy = rs->md.raid_disks - 1; | ||
1006 | break; | ||
1007 | case 4: | ||
1008 | case 5: | ||
1009 | case 6: | ||
1010 | redundancy = rs->raid_type->parity_devs; | ||
1011 | break; | ||
1012 | case 10: | ||
1013 | redundancy = raid10_md_layout_to_copies(mddev->layout) - 1; | ||
1014 | break; | ||
1015 | default: | ||
1016 | ti->error = "Unknown RAID type"; | ||
1017 | return -EINVAL; | ||
1018 | } | ||
1019 | |||
1020 | freshest = NULL; | 994 | freshest = NULL; |
1021 | rdev_for_each_safe(rdev, tmp, mddev) { | 995 | rdev_for_each_safe(rdev, tmp, mddev) { |
1022 | /* | 996 | /* |
@@ -1045,44 +1019,43 @@ static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs) | |||
1045 | break; | 1019 | break; |
1046 | default: | 1020 | default: |
1047 | dev = container_of(rdev, struct raid_dev, rdev); | 1021 | dev = container_of(rdev, struct raid_dev, rdev); |
1048 | if (redundancy--) { | 1022 | if (dev->meta_dev) |
1049 | if (dev->meta_dev) | 1023 | dm_put_device(ti, dev->meta_dev); |
1050 | dm_put_device(ti, dev->meta_dev); | ||
1051 | |||
1052 | dev->meta_dev = NULL; | ||
1053 | rdev->meta_bdev = NULL; | ||
1054 | 1024 | ||
1055 | if (rdev->sb_page) | 1025 | dev->meta_dev = NULL; |
1056 | put_page(rdev->sb_page); | 1026 | rdev->meta_bdev = NULL; |
1057 | 1027 | ||
1058 | rdev->sb_page = NULL; | 1028 | if (rdev->sb_page) |
1029 | put_page(rdev->sb_page); | ||
1059 | 1030 | ||
1060 | rdev->sb_loaded = 0; | 1031 | rdev->sb_page = NULL; |
1061 | 1032 | ||
1062 | /* | 1033 | rdev->sb_loaded = 0; |
1063 | * We might be able to salvage the data device | ||
1064 | * even though the meta device has failed. For | ||
1065 | * now, we behave as though '- -' had been | ||
1066 | * set for this device in the table. | ||
1067 | */ | ||
1068 | if (dev->data_dev) | ||
1069 | dm_put_device(ti, dev->data_dev); | ||
1070 | 1034 | ||
1071 | dev->data_dev = NULL; | 1035 | /* |
1072 | rdev->bdev = NULL; | 1036 | * We might be able to salvage the data device |
1037 | * even though the meta device has failed. For | ||
1038 | * now, we behave as though '- -' had been | ||
1039 | * set for this device in the table. | ||
1040 | */ | ||
1041 | if (dev->data_dev) | ||
1042 | dm_put_device(ti, dev->data_dev); | ||
1073 | 1043 | ||
1074 | list_del(&rdev->same_set); | 1044 | dev->data_dev = NULL; |
1045 | rdev->bdev = NULL; | ||
1075 | 1046 | ||
1076 | continue; | 1047 | list_del(&rdev->same_set); |
1077 | } | ||
1078 | ti->error = "Failed to load superblock"; | ||
1079 | return ret; | ||
1080 | } | 1048 | } |
1081 | } | 1049 | } |
1082 | 1050 | ||
1083 | if (!freshest) | 1051 | if (!freshest) |
1084 | return 0; | 1052 | return 0; |
1085 | 1053 | ||
1054 | if (validate_raid_redundancy(rs)) { | ||
1055 | rs->ti->error = "Insufficient redundancy to activate array"; | ||
1056 | return -EINVAL; | ||
1057 | } | ||
1058 | |||
1086 | /* | 1059 | /* |
1087 | * Validation of the freshest device provides the source of | 1060 | * Validation of the freshest device provides the source of |
1088 | * validation for the remaining devices. | 1061 | * validation for the remaining devices. |
@@ -1432,7 +1405,7 @@ static void raid_resume(struct dm_target *ti) | |||
1432 | 1405 | ||
1433 | static struct target_type raid_target = { | 1406 | static struct target_type raid_target = { |
1434 | .name = "raid", | 1407 | .name = "raid", |
1435 | .version = {1, 4, 0}, | 1408 | .version = {1, 4, 1}, |
1436 | .module = THIS_MODULE, | 1409 | .module = THIS_MODULE, |
1437 | .ctr = raid_ctr, | 1410 | .ctr = raid_ctr, |
1438 | .dtr = raid_dtr, | 1411 | .dtr = raid_dtr, |