diff options
Diffstat (limited to 'drivers/md/dm-raid.c')
-rw-r--r-- | drivers/md/dm-raid.c | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index 10635e965fec..4e79ebaab3c1 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c | |||
@@ -349,6 +349,7 @@ static int validate_region_size(struct raid_set *rs, unsigned long region_size) | |||
349 | static int validate_rebuild_devices(struct raid_set *rs) | 349 | static int validate_rebuild_devices(struct raid_set *rs) |
350 | { | 350 | { |
351 | unsigned i, rebuild_cnt = 0; | 351 | unsigned i, rebuild_cnt = 0; |
352 | unsigned rebuilds_per_group, copies, d; | ||
352 | 353 | ||
353 | if (!(rs->print_flags & DMPF_REBUILD)) | 354 | if (!(rs->print_flags & DMPF_REBUILD)) |
354 | return 0; | 355 | return 0; |
@@ -369,6 +370,37 @@ static int validate_rebuild_devices(struct raid_set *rs) | |||
369 | goto too_many; | 370 | goto too_many; |
370 | break; | 371 | break; |
371 | case 10: | 372 | case 10: |
373 | copies = raid10_md_layout_to_copies(rs->md.layout); | ||
374 | if (rebuild_cnt < copies) | ||
375 | break; | ||
376 | |||
377 | /* | ||
378 | * It is possible to have a higher rebuild count for RAID10, | ||
379 | * as long as the failed devices occur in different mirror | ||
380 | * groups (i.e. different stripes). | ||
381 | * | ||
382 | * Right now, we only allow for "near" copies. When other | ||
383 | * formats are added, we will have to check those too. | ||
384 | * | ||
385 | * When checking "near" format, make sure no adjacent devices | ||
386 | * have failed beyond what can be handled. In addition to the | ||
387 | * simple case where the number of devices is a multiple of the | ||
388 | * number of copies, we must also handle cases where the number | ||
389 | * of devices is not a multiple of the number of copies. | ||
390 | * E.g. dev1 dev2 dev3 dev4 dev5 | ||
391 | * A A B B C | ||
392 | * C D D E E | ||
393 | */ | ||
394 | rebuilds_per_group = 0; | ||
395 | for (i = 0; i < rs->md.raid_disks * copies; i++) { | ||
396 | d = i % rs->md.raid_disks; | ||
397 | if (!test_bit(In_sync, &rs->dev[d].rdev.flags) && | ||
398 | (++rebuilds_per_group >= copies)) | ||
399 | goto too_many; | ||
400 | if (!((i + 1) % copies)) | ||
401 | rebuilds_per_group = 0; | ||
402 | } | ||
403 | break; | ||
372 | default: | 404 | default: |
373 | DMERR("The rebuild parameter is not supported for %s", | 405 | DMERR("The rebuild parameter is not supported for %s", |
374 | rs->raid_type->name); | 406 | rs->raid_type->name); |
@@ -1385,7 +1417,7 @@ static void raid_resume(struct dm_target *ti) | |||
1385 | 1417 | ||
1386 | static struct target_type raid_target = { | 1418 | static struct target_type raid_target = { |
1387 | .name = "raid", | 1419 | .name = "raid", |
1388 | .version = {1, 3, 0}, | 1420 | .version = {1, 3, 1}, |
1389 | .module = THIS_MODULE, | 1421 | .module = THIS_MODULE, |
1390 | .ctr = raid_ctr, | 1422 | .ctr = raid_ctr, |
1391 | .dtr = raid_dtr, | 1423 | .dtr = raid_dtr, |