]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Grow.c
Detail: clean up handing of the 'info' we load from superblock.
[thirdparty/mdadm.git] / Grow.c
diff --git a/Grow.c b/Grow.c
index 4dfa344159040d90ee08eb1f4a0218b835a246d6..06343a0512e7226a98f6dac8c0b1a38eedd7d8ed 100644 (file)
--- a/Grow.c
+++ b/Grow.c
@@ -288,6 +288,11 @@ int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay, int
                return 1;
        } else if (strcmp(file, "internal") == 0) {
                int d;
+               if (st->ss->add_internal_bitmap == NULL) {
+                       fprintf(stderr, Name ": Internal bitmaps not supported "
+                               "with %s metadata\n", st->ss->name);
+                       return 1;
+               }
                for (d=0; d< st->max_devs; d++) {
                        mdu_disk_info_t disk;
                        char *dv;
@@ -541,7 +546,13 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
                return 1;
        }
        sra = sysfs_read(fd, 0, GET_LEVEL);
-       frozen = freeze_array(sra);
+       if (sra)
+               frozen = freeze_array(sra);
+       else {
+               fprintf(stderr, Name ": failed to read sysfs parameters for %s\n",
+                       devname);
+               return 1;
+       }
        if (frozen < 0) {
                fprintf(stderr, Name ": %s is performing resync/recovery and cannot"
                        " be reshaped\n", devname);
@@ -573,7 +584,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
                        goto release;
                }
                ioctl(fd, GET_ARRAY_INFO, &array);
-               size = get_component_size(fd);
+               size = get_component_size(fd)/2;
                if (size == 0)
                        size = array.size;
                if (!quiet)
@@ -581,7 +592,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
                                devname, size);
                changed = 1;
        } else {
-               size = get_component_size(fd);
+               size = get_component_size(fd)/2;
                if (size == 0)
                        size = array.size;
        }
@@ -748,6 +759,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
                                        if (err == EBUSY && 
                                            (array.state & (1<<MD_SB_BITMAP_PRESENT)))
                                                fprintf(stderr, "       Bitmap must be removed before level can be changed\n");
+                                       rv = 1;
                                }
                        }
                } else if (!changed && !quiet)
@@ -778,7 +790,6 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
 
                array.layout = parse_layout_faulty(layout_str);
                if (array.layout < 0) {
-                       int rv;
                        fprintf(stderr, Name ": %s: layout %s not understood for 'faulty' array\n",
                                devname, layout_str);
                        rv = 1;
@@ -926,8 +937,8 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
                 * old stripes and a whole number of new stripes.
                 * So LCM for (chunksize*datadisks).
                 */
-               a = ochunk/512 * odata;
-               b = nchunk/512 * ndata;
+               a = (ochunk/512) * odata;
+               b = (nchunk/512) * ndata;
                /* Find GCD */
                while (a != b) {
                        if (a < b)
@@ -936,13 +947,20 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
                                a -= b;
                }
                /* LCM == product / GCD */
-               blocks = ochunk/512 * nchunk/512 * odata * ndata / a;
+               blocks = (ochunk/512) * (nchunk/512) * odata * ndata / a;
 
                sysfs_free(sra);
                sra = sysfs_read(fd, 0,
                                 GET_COMPONENT|GET_DEVS|GET_OFFSET|GET_STATE|
                                 GET_CACHE);
 
+               if (!sra) {
+                       fprintf(stderr, Name ": %s: Cannot get array details from sysfs\n",
+                               devname);
+                       rv = 1;
+                       break;
+               }
+
                if (ndata == odata) {
                        /* Make 'blocks' bigger for better throughput, but
                         * not so big that we reject it below.
@@ -955,13 +973,6 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
                        fprintf(stderr, Name ": Need to backup %luK of critical "
                                "section..\n", blocks/2);
 
-               if (!sra) {
-                       fprintf(stderr, Name ": %s: Cannot get array details from sysfs\n",
-                               devname);
-                       rv = 1;
-                       break;
-               }
-
                if (blocks >= sra->component_size/2) {
                        fprintf(stderr, Name ": %s: Something wrong - reshape aborted\n",
                                devname);
@@ -1254,6 +1265,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
  * 
  */
 
+/* FIXME return status is never checked */
 int grow_backup(struct mdinfo *sra,
                unsigned long long offset, /* per device */
                unsigned long stripes, /* per device */
@@ -1278,7 +1290,7 @@ int grow_backup(struct mdinfo *sra,
                odata--;
        if (level == 6)
                odata--;
-       sysfs_set_num(sra, NULL, "suspend_hi", (offset + stripes * chunk/512) * 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) {
@@ -1306,10 +1318,10 @@ int grow_backup(struct mdinfo *sra,
        }
        if (part) {
                bsb.arraystart2 = __cpu_to_le64(offset * odata);
-               bsb.length2 = __cpu_to_le64(stripes * chunk/512 * odata);
+               bsb.length2 = __cpu_to_le64(stripes * (chunk/512) * odata);
        } else {
                bsb.arraystart = __cpu_to_le64(offset * odata);
-               bsb.length = __cpu_to_le64(stripes * chunk/512 * odata);
+               bsb.length = __cpu_to_le64(stripes * (chunk/512) * odata);
        }
        if (part)
                bsb.magic[15] = '2';
@@ -1336,16 +1348,19 @@ int grow_backup(struct mdinfo *sra,
                        bsb.sb_csum2 = bsb_csum((char*)&bsb,
                                                ((char*)&bsb.sb_csum2)-((char*)&bsb));
 
-               lseek64(destfd[i], destoffsets[i] - 4096, 0);
-               write(destfd[i], &bsb, 512);
+               if (lseek64(destfd[i], destoffsets[i] - 4096, 0) != destoffsets[i] - 4096)
+                       rv = 1;
+               rv = rv ?: write(destfd[i], &bsb, 512);
                if (destoffsets[i] > 4096) {
-                       lseek64(destfd[i], destoffsets[i]+stripes*chunk*odata, 0);
-                       write(destfd[i], &bsb, 512);
+                       if (lseek64(destfd[i], destoffsets[i]+stripes*chunk*odata, 0) !=
+                           destoffsets[i]+stripes*chunk*odata)
+                               rv = 1;
+                       rv = rv ?: write(destfd[i], &bsb, 512);
                }
                fsync(destfd[i]);
        }
 
-       return 0;
+       return rv;
 }
 
 /* in 2.6.30, the value reported by sync_completed can be
@@ -1358,6 +1373,7 @@ int grow_backup(struct mdinfo *sra,
  * The various caller give appropriate values so that
  * every works.
  */
+/* FIXME return value is often ignored */
 int wait_backup(struct mdinfo *sra,
                unsigned long long offset, /* per device */
                unsigned long long blocks, /* per device */
@@ -1371,6 +1387,7 @@ int wait_backup(struct mdinfo *sra,
        int fd = sysfs_get_fd(sra, NULL, "sync_completed");
        unsigned long long completed;
        int i;
+       int rv;
 
        if (fd < 0)
                return -1;
@@ -1402,24 +1419,28 @@ int wait_backup(struct mdinfo *sra,
                bsb.length = __cpu_to_le64(0);
        }
        bsb.mtime = __cpu_to_le64(time(0));
+       rv = 0;
        for (i = 0; i < dests; i++) {
                bsb.devstart = __cpu_to_le64(destoffsets[i]/512);
                bsb.sb_csum = bsb_csum((char*)&bsb, ((char*)&bsb.sb_csum)-((char*)&bsb));
                if (memcmp(bsb.magic, "md_backup_data-2", 16) == 0)
                        bsb.sb_csum2 = bsb_csum((char*)&bsb,
                                                ((char*)&bsb.sb_csum2)-((char*)&bsb));
-               lseek64(destfd[i], destoffsets[i]-4096, 0);
-               write(destfd[i], &bsb, 512);
+               if (lseek64(destfd[i], destoffsets[i]-4096, 0) !=
+                   destoffsets[i]-4096)
+                       rv = 1;
+               rv = rv ?: write(destfd[i], &bsb, 512);
                fsync(destfd[i]);
        }
-       return 0;
+       return rv;
 }
 
 static void fail(char *msg)
 {
-       write(2, msg, strlen(msg));
-       write(2, "\n", 1);
-       exit(1);
+       int rv;
+       rv = write(2, msg, strlen(msg));
+       rv |= write(2, "\n", 1);
+       exit(rv ? 1 : 2);
 }
 
 static char *abuf, *bbuf;
@@ -1455,8 +1476,12 @@ static void validate(int afd, int bfd, unsigned long long offset)
                        free(abuf);
                        free(bbuf);
                        abuflen = len;
-                       posix_memalign((void**)&abuf, 4096, abuflen);
-                       posix_memalign((void**)&bbuf, 4096, abuflen);
+                       if (posix_memalign((void**)&abuf, 4096, abuflen) ||
+                           posix_memalign((void**)&bbuf, 4096, abuflen)) {
+                               abuflen = 0;
+                               /* just stop validating on mem-alloc failure */
+                               return;
+                       }
                }
 
                lseek64(bfd, offset, 0);
@@ -1511,7 +1536,9 @@ static int child_grow(int afd, struct mdinfo *sra, unsigned long stripes,
        char *buf;
        int degraded = 0;
 
-       posix_memalign((void**)&buf, 4096, disks * chunk);
+       if (posix_memalign((void**)&buf, 4096, disks * chunk))
+               /* Don't start the 'reshape' */
+               return 0;
        sysfs_set_num(sra, NULL, "suspend_hi", 0);
        sysfs_set_num(sra, NULL, "suspend_lo", 0);
        grow_backup(sra, 0, stripes,
@@ -1519,10 +1546,10 @@ static int child_grow(int afd, struct mdinfo *sra, unsigned long stripes,
                    dests, destfd, destoffsets,
                    0, &degraded, buf);
        validate(afd, destfd[0], destoffsets[0]);
-       wait_backup(sra, 0, stripes * chunk / 512, stripes * chunk / 512,
+       wait_backup(sra, 0, stripes * (chunk / 512), stripes * (chunk / 512),
                    dests, destfd, destoffsets,
                    0);
-       sysfs_set_num(sra, NULL, "suspend_lo", (stripes * chunk/512) * data);
+       sysfs_set_num(sra, NULL, "suspend_lo", (stripes * (chunk/512)) * data);
        free(buf);
        /* FIXME this should probably be numeric */
        sysfs_set_str(sra, NULL, "sync_max", "max");
@@ -1539,13 +1566,14 @@ static int child_shrink(int afd, struct mdinfo *sra, unsigned long stripes,
        int rv;
        int degraded = 0;
 
-       posix_memalign((void**)&buf, 4096, disks * chunk);
-       start = sra->component_size - stripes * chunk/512;
+       if (posix_memalign((void**)&buf, 4096, disks * chunk))
+               return 0;
+       start = sra->component_size - stripes * (chunk/512);
        sysfs_set_num(sra, NULL, "sync_max", start);
        sysfs_set_str(sra, NULL, "sync_action", "reshape");
        sysfs_set_num(sra, NULL, "suspend_lo", 0);
        sysfs_set_num(sra, NULL, "suspend_hi", 0);
-       rv = wait_backup(sra, 0, start - stripes * chunk/512, stripes * chunk/512,
+       rv = wait_backup(sra, 0, start - stripes * (chunk/512), stripes * (chunk/512),
                         dests, destfd, destoffsets, 0);
        if (rv < 0)
                return 0;
@@ -1555,9 +1583,9 @@ static int child_shrink(int afd, struct mdinfo *sra, unsigned long stripes,
                    dests, destfd, destoffsets,
                    0, &degraded, buf);
        validate(afd, destfd[0], destoffsets[0]);
-       wait_backup(sra, start, stripes*chunk/512, 0,
+       wait_backup(sra, start, stripes*(chunk/512), 0,
                    dests, destfd, destoffsets, 0);
-       sysfs_set_num(sra, NULL, "suspend_lo", (stripes * chunk/512) * data);
+       sysfs_set_num(sra, NULL, "suspend_lo", (stripes * (chunk/512)) * data);
        free(buf);
        /* FIXME this should probably be numeric */
        sysfs_set_str(sra, NULL, "sync_max", "max");
@@ -1578,7 +1606,8 @@ static int child_same_size(int afd, struct mdinfo *sra, unsigned long stripes,
        int degraded = 0;
 
 
-       posix_memalign((void**)&buf, 4096, disks * chunk);
+       if (posix_memalign((void**)&buf, 4096, disks * chunk))
+               return 0;
 
        sysfs_set_num(sra, NULL, "suspend_lo", 0);
        sysfs_set_num(sra, NULL, "suspend_hi", 0);
@@ -1591,7 +1620,7 @@ static int child_same_size(int afd, struct mdinfo *sra, unsigned long stripes,
                    disks, chunk, level, layout,
                    dests, destfd, destoffsets,
                    0, &degraded, buf);
-       grow_backup(sra, (start + stripes) * chunk/512, stripes,
+       grow_backup(sra, (start + stripes) * (chunk/512), stripes,
                    fds, offsets,
                    disks, chunk, level, layout,
                    dests, destfd, destoffsets,
@@ -1601,16 +1630,16 @@ static int child_same_size(int afd, struct mdinfo *sra, unsigned long stripes,
        start += stripes * 2; /* where to read next */
        size = sra->component_size / (chunk/512);
        while (start < size) {
-               if (wait_backup(sra, (start-stripes*2)*chunk/512,
-                               stripes*chunk/512, 0,
+               if (wait_backup(sra, (start-stripes*2)*(chunk/512),
+                               stripes*(chunk/512), 0,
                                dests, destfd, destoffsets,
                                part) < 0)
                        return 0;
-               sysfs_set_num(sra, NULL, "suspend_lo", start*chunk/512 * data);
+               sysfs_set_num(sra, NULL, "suspend_lo", start*(chunk/512) * data);
                if (start + stripes > size)
                        tailstripes = (size - start);
 
-               grow_backup(sra, start*chunk/512, tailstripes,
+               grow_backup(sra, start*(chunk/512), tailstripes,
                            fds, offsets,
                            disks, chunk, level, layout,
                            dests, destfd, destoffsets,
@@ -1619,15 +1648,15 @@ static int child_same_size(int afd, struct mdinfo *sra, unsigned long stripes,
                part = 1 - part;
                validate(afd, destfd[0], destoffsets[0]);
        }
-       if (wait_backup(sra, (start-stripes*2) * chunk/512, stripes * chunk/512, 0,
+       if (wait_backup(sra, (start-stripes*2) * (chunk/512), stripes * (chunk/512), 0,
                        dests, destfd, destoffsets,
                        part) < 0)
                return 0;
-       sysfs_set_num(sra, NULL, "suspend_lo", ((start-stripes)*chunk/512) * data);
-       wait_backup(sra, (start-stripes) * chunk/512, tailstripes * chunk/512, 0,
+       sysfs_set_num(sra, NULL, "suspend_lo", ((start-stripes)*(chunk/512)) * data);
+       wait_backup(sra, (start-stripes) * (chunk/512), tailstripes * (chunk/512), 0,
                    dests, destfd, destoffsets,
                    1-part);
-       sysfs_set_num(sra, NULL, "suspend_lo", (size*chunk/512) * data);
+       sysfs_set_num(sra, NULL, "suspend_lo", (size*(chunk/512)) * data);
        sysfs_set_num(sra, NULL, "sync_speed_min", speed);
        free(buf);
        return 1;
@@ -1791,7 +1820,7 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist, int cnt
                }
                /* There should be a duplicate backup superblock 4k before here */
                if (lseek64(fd, -4096, 1) < 0 ||
-                   read(fd, &bsb2, 4096) != 4096)
+                   read(fd, &bsb2, sizeof(bsb2)) != sizeof(bsb2))
                        goto second_fail; /* Cannot find leading superblock */
                if (bsb.magic[15] == '1')
                        bsbsize = offsetof(struct mdp_backup_super, pad1);
@@ -1954,7 +1983,13 @@ int Grow_continue(int mdfd, struct supertype *st, struct mdinfo *info,
        /* make sure reshape doesn't progress until we are ready */
        sysfs_set_str(info, NULL, "sync_max", "0");
        sysfs_set_str(info, NULL, "array_state", "active"); /* FIXME or clean */
-       
+
+       sra = sysfs_read(-1, devname2devnum(info->sys_name),
+                        GET_COMPONENT|GET_DEVS|GET_OFFSET|GET_STATE|
+                        GET_CACHE);
+       if (!sra)
+               return 1;
+
        /* ndisks is not growing, so raid_disks is old and +delta is new */
        odisks = info->array.raid_disks;
        ndisks = odisks + info->delta_disks;
@@ -1967,9 +2002,8 @@ int Grow_continue(int mdfd, struct supertype *st, struct mdinfo *info,
        ochunk = info->array.chunk_size;
        nchunk = info->new_chunk;
 
-
-       a = ochunk/512 * odata;
-       b = nchunk/512 * ndata;
+       a = (ochunk/512) * odata;
+       b = (nchunk/512) * ndata;
        /* Find GCD */
        while (a != b) {
                if (a < b)
@@ -1978,12 +2012,7 @@ int Grow_continue(int mdfd, struct supertype *st, struct mdinfo *info,
                        a -= b;
        }
        /* LCM == product / GCD */
-       blocks = ochunk/512 * nchunk/512 * odata * ndata / a;
-
-       sra = sysfs_read(-1, devname2devnum(info->sys_name),
-                        GET_COMPONENT|GET_DEVS|GET_OFFSET|GET_STATE|
-                        GET_CACHE);
-
+       blocks = (ochunk/512) * (nchunk/512) * odata * ndata / a;
 
        if (ndata == odata)
                while (blocks * 32 < sra->component_size &&