]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Make Assemble/Force work on raid6 with 2 missing devices.
authorNeil Brown <neilb@suse.de>
Thu, 14 Dec 2006 06:30:51 +0000 (17:30 +1100)
committerNeil Brown <neilb@suse.de>
Thu, 14 Dec 2006 06:30:51 +0000 (17:30 +1100)
Previously it onl worked when one missing device.
Also split the "force" update_super method into two and it
is really serving two functions.

Assemble.c
ChangeLog
super0.c
super1.c
tests/06update-uuid [new file with mode: 0644]

index 6ca54f9c35a684c579ad070ea0f2e172c27688d2..23e3583069e54b73480e11df612d9c49e81aaa89 100644 (file)
@@ -656,7 +656,9 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
                        continue;
                }
                info.events = devices[most_recent].events;
-               st->ss->update_super(&info, super, "force", devices[chosen_drive].devname, verbose, 0, NULL);
+               st->ss->update_super(&info, super, "force-one",
+                                    devices[chosen_drive].devname, verbose,
+                                    0, NULL);
 
                if (st->ss->store_super(st, fd, super)) {
                        close(fd);
@@ -752,10 +754,10 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
                }
 #endif
        }
-       if (force && okcnt == info.array.raid_disks-1) {
-               /* FIXME check event count */
-               change += st->ss->update_super(&info, super, "force",
-                                       devices[chosen_drive].devname, verbose, 0, NULL);
+       if (force && okcnt < info.array.raid_disks) {
+               change += st->ss->update_super(&info, super, "force-array",
+                                       devices[chosen_drive].devname, verbose,
+                                              0, NULL);
        }
 
        if (change) {
index 81d51d326c9d1c129246de26b9438d92e7bebcf2..6ea0c3b5ad6bd8534f259913e069e98192154e7c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,10 @@ Changes Prior to this release
     -   Fixed UUID printing in "--detail --brief" for version1 metadata.
     -   --update=resync did exactly the wrong thing for version1 metadata.
        It caused a resync to not happen, rather than to happen.
+    -   Allow --assemble --force to mark a raid6 clean when it has two
+       missing devices (which is needed else if won't assemble.
+       Without this fix it would only assemble if one or zero
+       missing devices.
 
 Changes Prior to 2.5.6 release
     -   Fix bug which meant "bitmap=xxx" in mdadm.conf was not handled
index 9e83193bddbadc20ecf0bb59edb24b7233eb8d72..2060e93dd22a4823c027026759a92430567207ef 100644 (file)
--- a/super0.c
+++ b/super0.c
@@ -411,13 +411,21 @@ static int update_super0(struct mdinfo *info, void *sbv, char *update,
                        } else if (i >= sb->raid_disks && sb->disks[i].number == 0)
                                sb->disks[i].state = 0;
        }
-       if (strcmp(update, "force")==0) {
+       if (strcmp(update, "force-one")==0) {
+               /* Not enough devices for a working array, so
+                * bring this one up-to-date.
+                */
                __u32 ehi = sb->events_hi, elo = sb->events_lo;
                sb->events_hi = (info->events>>32) & 0xFFFFFFFF;
                sb->events_lo = (info->events) & 0xFFFFFFFF;
                if (sb->events_hi != ehi ||
                    sb->events_lo != elo)
                        rv = 1;
+       }
+       if (strcmp(update, "force-array")==0) {
+               /* degraded array and 'force' requested, so
+                * maybe need to mark it 'clean'
+                */
                if ((sb->level == 5 || sb->level == 4 || sb->level == 6) &&
                    (sb->state & (1 << MD_SB_CLEAN)) == 0) {
                        /* need to force clean */
index c8d63cf82e7f5ab29670961d8aca6bab59eb299a..bf26cfa47c3a3962ee447935859ff5c6fe296cd8 100644 (file)
--- a/super1.c
+++ b/super1.c
@@ -485,10 +485,18 @@ static int update_super1(struct mdinfo *info, void *sbv, char *update,
        int rv = 0;
        struct mdp_superblock_1 *sb = sbv;
 
-       if (strcmp(update, "force")==0) {
+       if (strcmp(update, "force-one")==0) {
+               /* Not enough devices for a working array,
+                * so bring this one up-to-date
+                */
                if (sb->events != __cpu_to_le64(info->events))
                        rv = 1;
                sb->events = __cpu_to_le64(info->events);
+       }
+       if (strcmp(update, "force-array")==0) {
+               /* Degraded array and 'force' requests to
+                * maybe need to mark it 'clean'.
+                */
                switch(__le32_to_cpu(sb->level)) {
                case 5: case 4: case 6:
                        /* need to force clean */
diff --git a/tests/06update-uuid b/tests/06update-uuid
new file mode 100644 (file)
index 0000000..e69de29