Commit 327372797c88b24953f454cd51a3734c02697bdd
Committed by
Alasdair G Kergon
1 parent
b12d437b73
Exists in
master
and in
6 other branches
dm raid: add md raid1 support
Support the MD RAID1 personality through dm-raid. Signed-off-by: Jonathan Brassow <jbrassow@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Showing 1 changed file with 39 additions and 10 deletions Side-by-side Diff
drivers/md/dm-raid.c
... | ... | @@ -8,6 +8,7 @@ |
8 | 8 | #include <linux/slab.h> |
9 | 9 | |
10 | 10 | #include "md.h" |
11 | +#include "raid1.h" | |
11 | 12 | #include "raid5.h" |
12 | 13 | #include "bitmap.h" |
13 | 14 | |
... | ... | @@ -72,6 +73,7 @@ |
72 | 73 | const unsigned level; /* RAID level. */ |
73 | 74 | const unsigned algorithm; /* RAID algorithm. */ |
74 | 75 | } raid_types[] = { |
76 | + {"raid1", "RAID1 (mirroring)", 0, 2, 1, 0 /* NONE */}, | |
75 | 77 | {"raid4", "RAID4 (dedicated parity disk)", 1, 2, 5, ALGORITHM_PARITY_0}, |
76 | 78 | {"raid5_la", "RAID5 (left asymmetric)", 1, 2, 5, ALGORITHM_LEFT_ASYMMETRIC}, |
77 | 79 | {"raid5_ra", "RAID5 (right asymmetric)", 1, 2, 5, ALGORITHM_RIGHT_ASYMMETRIC}, |
... | ... | @@ -105,7 +107,8 @@ |
105 | 107 | } |
106 | 108 | |
107 | 109 | sectors_per_dev = ti->len; |
108 | - if (sector_div(sectors_per_dev, (raid_devs - raid_type->parity_devs))) { | |
110 | + if ((raid_type->level > 1) && | |
111 | + sector_div(sectors_per_dev, (raid_devs - raid_type->parity_devs))) { | |
109 | 112 | ti->error = "Target length not divisible by number of data devices"; |
110 | 113 | return ERR_PTR(-EINVAL); |
111 | 114 | } |
112 | 115 | |
113 | 116 | |
... | ... | @@ -329,13 +332,16 @@ |
329 | 332 | |
330 | 333 | /* |
331 | 334 | * Possible arguments are... |
332 | - * RAID456: | |
333 | 335 | * <chunk_size> [optional_args] |
334 | 336 | * |
335 | - * Optional args: | |
336 | - * [[no]sync] Force or prevent recovery of the entire array | |
337 | + * Argument definitions | |
338 | + * <chunk_size> The number of sectors per disk that | |
339 | + * will form the "stripe" | |
340 | + * [[no]sync] Force or prevent recovery of the | |
341 | + * entire array | |
337 | 342 | * [rebuild <idx>] Rebuild the drive indicated by the index |
338 | - * [daemon_sleep <ms>] Time between bitmap daemon work to clear bits | |
343 | + * [daemon_sleep <ms>] Time between bitmap daemon work to | |
344 | + * clear bits | |
339 | 345 | * [min_recovery_rate <kB/sec/disk>] Throttle RAID initialization |
340 | 346 | * [max_recovery_rate <kB/sec/disk>] Throttle RAID initialization |
341 | 347 | * [write_mostly <idx>] Indicate a write mostly drive via index |
342 | 348 | |
343 | 349 | |
... | ... | @@ -352,11 +358,21 @@ |
352 | 358 | |
353 | 359 | /* |
354 | 360 | * First, parse the in-order required arguments |
361 | + * "chunk_size" is the only argument of this type. | |
355 | 362 | */ |
356 | - if ((strict_strtoul(argv[0], 10, &value) < 0) || | |
357 | - !is_power_of_2(value) || (value < 8)) { | |
363 | + if ((strict_strtoul(argv[0], 10, &value) < 0)) { | |
358 | 364 | rs->ti->error = "Bad chunk size"; |
359 | 365 | return -EINVAL; |
366 | + } else if (rs->raid_type->level == 1) { | |
367 | + if (value) | |
368 | + DMERR("Ignoring chunk size parameter for RAID 1"); | |
369 | + value = 0; | |
370 | + } else if (!is_power_of_2(value)) { | |
371 | + rs->ti->error = "Chunk size must be a power of 2"; | |
372 | + return -EINVAL; | |
373 | + } else if (value < 8) { | |
374 | + rs->ti->error = "Chunk size value is too small"; | |
375 | + return -EINVAL; | |
360 | 376 | } |
361 | 377 | |
362 | 378 | rs->md.new_chunk_sectors = rs->md.chunk_sectors = value; |
... | ... | @@ -413,8 +429,12 @@ |
413 | 429 | } |
414 | 430 | |
415 | 431 | if (!strcasecmp(key, "rebuild")) { |
416 | - if (++rebuild_cnt > rs->raid_type->parity_devs) { | |
417 | - rs->ti->error = "Too many rebuild drives given"; | |
432 | + rebuild_cnt++; | |
433 | + if (((rs->raid_type->level != 1) && | |
434 | + (rebuild_cnt > rs->raid_type->parity_devs)) || | |
435 | + ((rs->raid_type->level == 1) && | |
436 | + (rebuild_cnt > (rs->md.raid_disks - 1)))) { | |
437 | + rs->ti->error = "Too many rebuild devices specified for given RAID type"; | |
418 | 438 | return -EINVAL; |
419 | 439 | } |
420 | 440 | if (value > rs->md.raid_disks) { |
... | ... | @@ -507,6 +527,11 @@ |
507 | 527 | else |
508 | 528 | rs->ti->split_io = region_size; |
509 | 529 | |
530 | + if (rs->md.chunk_sectors) | |
531 | + rs->ti->split_io = rs->md.chunk_sectors; | |
532 | + else | |
533 | + rs->ti->split_io = region_size; | |
534 | + | |
510 | 535 | /* Assume there are no metadata devices until the drives are parsed */ |
511 | 536 | rs->md.persistent = 0; |
512 | 537 | rs->md.external = 1; |
... | ... | @@ -525,6 +550,9 @@ |
525 | 550 | { |
526 | 551 | struct raid_set *rs = container_of(cb, struct raid_set, callbacks); |
527 | 552 | |
553 | + if (rs->raid_type->level == 1) | |
554 | + return md_raid1_congested(&rs->md, bits); | |
555 | + | |
528 | 556 | return md_raid5_congested(&rs->md, bits); |
529 | 557 | } |
530 | 558 | |
... | ... | @@ -955,6 +983,7 @@ |
955 | 983 | rs->callbacks.congested_fn = raid_is_congested; |
956 | 984 | dm_table_add_target_callbacks(ti->table, &rs->callbacks); |
957 | 985 | |
986 | + mddev_suspend(&rs->md); | |
958 | 987 | return 0; |
959 | 988 | |
960 | 989 | bad: |
... | ... | @@ -1147,7 +1176,7 @@ |
1147 | 1176 | |
1148 | 1177 | static struct target_type raid_target = { |
1149 | 1178 | .name = "raid", |
1150 | - .version = {1, 0, 0}, | |
1179 | + .version = {1, 1, 0}, | |
1151 | 1180 | .module = THIS_MODULE, |
1152 | 1181 | .ctr = raid_ctr, |
1153 | 1182 | .dtr = raid_dtr, |