]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Grow: handle array going degraded during reshape.
authorNeilBrown <neilb@suse.de>
Fri, 6 Nov 2009 02:56:05 +0000 (13:56 +1100)
committerNeilBrown <neilb@suse.de>
Fri, 6 Nov 2009 02:56:05 +0000 (13:56 +1100)
If an array goes degraded during reshape, we need to
adjust the devices we read from so as not to back up
stale data.

Signed-off-by: NeilBrown <neilb@suse.de>
Grow.c

diff --git a/Grow.c b/Grow.c
index deff0e0df697f6d92223a095fb7e75dd85b738b5..31007ae67735e4c5acfea650376bc5eb03ad9f59 100644 (file)
--- a/Grow.c
+++ b/Grow.c
@@ -1205,7 +1205,7 @@ int grow_backup(struct mdinfo *sra,
                int *sources, unsigned long long *offsets,
                int disks, int chunk, int level, int layout,
                int dests, int *destfd, unsigned long long *destoffsets,
-               int part,
+               int part, int *degraded,
                char *buf)
 {
        /* Backup 'blocks' sectors at 'offset' on each device of the array,
@@ -1217,12 +1217,38 @@ int grow_backup(struct mdinfo *sra,
        int odata = disks;
        int rv = 0;
        int i;
+       unsigned long long new_degraded;
        //printf("offset %llu\n", offset);
        if (level >= 4)
                odata--;
        if (level == 6)
                odata--;
        sysfs_set_num(sra, NULL, "suspend_hi", (offset + stripes * chunk/512) * odata);
+       /* Check that array hasn't become degraded, else we might backup the wrong data */
+       sysfs_get_ll(sra, NULL, "degraded", &new_degraded);
+       if (new_degraded != *degraded) {
+               /* check each device to ensure it is still working */
+               struct mdinfo *sd;
+               for (sd = sra->devs ; sd ; sd = sd->next) {
+                       if (sd->disk.state & (1<<MD_DISK_FAULTY))
+                               continue;
+                       if (sd->disk.state & (1<<MD_DISK_SYNC)) {
+                               char sbuf[20];
+                               if (sysfs_get_str(sra, sd, "state", sbuf, 20) < 0 ||
+                                   strstr(sbuf, "faulty") ||
+                                   strstr(sbuf, "in_sync") == NULL) {
+                                       /* this device is dead */
+                                       sd->disk.state = (1<<MD_DISK_FAULTY);
+                                       if (sd->disk.raid_disk >= 0 &&
+                                           sources[sd->disk.raid_disk] >= 0) {
+                                               close(sources[sd->disk.raid_disk]);
+                                               sources[sd->disk.raid_disk] = -1;
+                                       }
+                               }
+                       }
+               }
+               *degraded = new_degraded;
+       }
        if (part) {
                bsb.arraystart2 = __cpu_to_le64(offset * odata);
                bsb.length2 = __cpu_to_le64(stripes * chunk/512 * odata);
@@ -1422,6 +1448,7 @@ static int child_grow(int afd, struct mdinfo *sra, unsigned long stripes,
                      int dests, int *destfd, unsigned long long *destoffsets)
 {
        char *buf;
+       int degraded = 0;
 
        posix_memalign((void**)&buf, 4096, disks * chunk);
        sysfs_set_num(sra, NULL, "suspend_hi", 0);
@@ -1429,7 +1456,7 @@ static int child_grow(int afd, struct mdinfo *sra, unsigned long stripes,
        grow_backup(sra, 0, stripes,
                    fds, offsets, disks, chunk, level, layout,
                    dests, destfd, destoffsets,
-                   0, buf);
+                   0, &degraded, buf);
        validate(afd, destfd[0], destoffsets[0]);
        wait_backup(sra, 0, stripes * chunk / 512, stripes * chunk / 512,
                    dests, destfd, destoffsets,
@@ -1449,6 +1476,7 @@ static int child_shrink(int afd, struct mdinfo *sra, unsigned long stripes,
        char *buf;
        unsigned long long start;
        int rv;
+       int degraded = 0;
 
        posix_memalign((void**)&buf, 4096, disks * chunk);
        start = sra->component_size - stripes * chunk/512;
@@ -1464,7 +1492,7 @@ static int child_shrink(int afd, struct mdinfo *sra, unsigned long stripes,
                    fds, offsets,
                    disks, chunk, level, layout,
                    dests, destfd, destoffsets,
-                   0, buf);
+                   0, &degraded, buf);
        validate(afd, destfd[0], destoffsets[0]);
        wait_backup(sra, start, stripes*chunk/512, 0,
                    dests, destfd, destoffsets, 0);
@@ -1486,6 +1514,7 @@ static int child_same_size(int afd, struct mdinfo *sra, unsigned long stripes,
        int part;
        char *buf;
        unsigned long long speed;
+       int degraded = 0;
 
 
        posix_memalign((void**)&buf, 4096, disks * chunk);
@@ -1500,12 +1529,12 @@ static int child_same_size(int afd, struct mdinfo *sra, unsigned long stripes,
                    fds, offsets,
                    disks, chunk, level, layout,
                    dests, destfd, destoffsets,
-                   0, buf);
+                   0, &degraded, buf);
        grow_backup(sra, (start + stripes) * chunk/512, stripes,
                    fds, offsets,
                    disks, chunk, level, layout,
                    dests, destfd, destoffsets,
-                   1, buf);
+                   1, &degraded, buf);
        validate(afd, destfd[0], destoffsets[0]);
        part = 0;
        start += stripes * 2; /* where to read next */
@@ -1524,7 +1553,7 @@ static int child_same_size(int afd, struct mdinfo *sra, unsigned long stripes,
                            fds, offsets,
                            disks, chunk, level, layout,
                            dests, destfd, destoffsets,
-                           part, buf);
+                           part, &degraded, buf);
                start += stripes;
                part = 1 - part;
                validate(afd, destfd[0], destoffsets[0]);