summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Brown <neilb@suse.de>2008-04-28 16:30:09 +1000
committerNeil Brown <neilb@suse.de>2008-04-28 16:30:09 +1000
commit6fb79233b050b4a3575f0e466ab04b5d301ac1de (patch)
tree929ec991db01903aa8315f47592d30ecc1793547
parent3cdfb6a71259759f24f48d4c14b76e056d0bfaf6 (diff)
downloadmdadm-6fb79233b050b4a3575f0e466ab04b5d301ac1de.tar.gz
mdadm-6fb79233b050b4a3575f0e466ab04b5d301ac1de.tar.xz
mdadm-6fb79233b050b4a3575f0e466ab04b5d301ac1de.zip
Allow creation of a RAID6 with a single missing device.
This did not work before as we couldn't mark it clean as there would be some parity blocks out of sync, and raid6 will not assemble a dirty degraded array. So make such arrays doubly degraded (the last device becomes a spare) and clean.
-rw-r--r--ChangeLog1
-rw-r--r--Create.c20
2 files changed, 19 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index df88d29..c4d996d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -6,6 +6,7 @@ Changes Prior to this release
- For v0.90 superblocks, print the 'Events' count as a real count,
not 2 numbers separated by a dot.
- Updates some URLs in the man page.
+ - Allow creation of a RAID6 with exactly one missing device.
Changes Prior to 2.6.4 release
- Make "--create --auto=mdp" work for non-standard device names.
diff --git a/Create.c b/Create.c
index b7a3f7d..8407579 100644
--- a/Create.c
+++ b/Create.c
@@ -63,6 +63,7 @@ int Create(struct supertype *st, char *mddev, int mdfd,
int fail=0, warn=0;
struct stat stb;
int first_missing = subdevs * 2;
+ int second_missing = subdevs * 2;
int missing_disks = 0;
int insert_point = subdevs * 2; /* where to insert a missing drive */
int pass;
@@ -203,6 +204,8 @@ int Create(struct supertype *st, char *mddev, int mdfd,
if (strcasecmp(dname, "missing")==0) {
if (first_missing > dnum)
first_missing = dnum;
+ if (second_missing > dnum && dnum > first_missing)
+ second_missing = dnum;
missing_disks ++;
continue;
}
@@ -341,6 +344,18 @@ int Create(struct supertype *st, char *mddev, int mdfd,
break;
}
}
+ /* For raid6, if creating with 1 missing drive, make a good drive
+ * into a spare, else the create will fail
+ */
+ if (assume_clean == 0 && force == 0 && first_missing < raiddisks &&
+ second_missing >= raiddisks && level == 6) {
+ insert_point = raiddisks - 1;
+ if (insert_point == first_missing)
+ insert_point--;
+ sparedisks ++;
+ info.array.active_disks--;
+ missing_disks++;
+ }
if (level <= 0 && first_missing != subdevs * 2) {
fprintf(stderr,
@@ -360,11 +375,12 @@ int Create(struct supertype *st, char *mddev, int mdfd,
if (fstat(mdfd, &stb)==0)
info.array.md_minor = minor(stb.st_rdev);
info.array.not_persistent = 0;
- /*** FIX: Need to do something about RAID-6 here ***/
+
if ( ( (level == 4 || level == 5) &&
(insert_point < raiddisks || first_missing < raiddisks) )
||
- ( level == 6 && missing_disks == 2)
+ ( level == 6 && (insert_point < raiddisks
+ || second_missing < raiddisks))
||
assume_clean
)