]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Grow.c
imsm: do not publish OROM/EFI unsupported arrays
[thirdparty/mdadm.git] / Grow.c
diff --git a/Grow.c b/Grow.c
index ea1d57fe53b06e73d16fbf374cb96df5c203024a..d596c2de7a7df6bd9ebe0eafdb3e55c365f66f9b 100644 (file)
--- a/Grow.c
+++ b/Grow.c
@@ -1506,7 +1506,10 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
        info.component_size = size*2;
        info.new_level = level;
        info.new_chunk = chunksize * 1024;
-       if (raid_disks)
+       if (info.array.level == LEVEL_CONTAINER) {
+               info.delta_disks = UnSet;
+               info.array.raid_disks = raid_disks;
+       } else if (raid_disks)
                info.delta_disks = raid_disks - info.array.raid_disks;
        else
                info.delta_disks = UnSet;
@@ -1646,14 +1649,24 @@ static int reshape_array(char *container, int fd, char *devname,
        int done;
        struct mdinfo *sra = NULL;
 
-       msg = analyse_change(info, &reshape);
+       if (info->reshape_active) {
+               int new_level = info->new_level;
+               info->new_level = UnSet;
+               msg = analyse_change(info, &reshape);
+               info->new_level = new_level;
+               if (!restart)
+                       /* Make sure the array isn't read-only */
+                       ioctl(fd, RESTART_ARRAY_RW, 0);
+       } else
+               msg = analyse_change(info, &reshape);
        if (msg) {
                fprintf(stderr, Name ": %s\n", msg);
                goto release;
        }
-       if (reshape.level != info->array.level ||
-           reshape.before.layout != info->array.layout ||
-           reshape.before.data_disks + reshape.parity != info->array.raid_disks) {
+       if (restart &&
+           (reshape.level != info->array.level ||
+            reshape.before.layout != info->array.layout ||
+            reshape.before.data_disks + reshape.parity != info->array.raid_disks)) {
                fprintf(stderr, Name ": reshape info is not in native format -"
                        " cannot continue.\n");
                goto release;
@@ -1675,6 +1688,7 @@ static int reshape_array(char *container, int fd, char *devname,
         * freeze_array and freeze_container.
         */
        sysfs_freeze_array(info);
+       /* Check we have enough spares to not be degraded */
        spares_needed = max(reshape.before.data_disks,
                            reshape.after.data_disks)
                + reshape.parity - array.raid_disks;
@@ -1691,8 +1705,22 @@ static int reshape_array(char *container, int fd, char *devname,
                        info->array.spare_disks);
                goto release;
        }
+       /* Check we have enough spares to not fail */
+       spares_needed = max(reshape.before.data_disks,
+                           reshape.after.data_disks)
+               - array.raid_disks;
+       if ((info->new_level > 1 || info->new_level == 0) &&
+           spares_needed > info->array.spare_disks) {
+               fprintf(stderr,
+                       Name ": Need %d spare%s to create working array,"
+                       " and only have %d.\n",
+                       spares_needed,
+                       spares_needed == 1 ? "" : "s", 
+                       info->array.spare_disks);
+               goto release;
+       }
 
-       if (reshape.level != info->array.level) {
+       if (reshape.level != array.level) {
                char *c = map_num(pers, reshape.level);
                int err;
                if (c == NULL)
@@ -1712,7 +1740,7 @@ static int reshape_array(char *container, int fd, char *devname,
                if (!quiet)
                        fprintf(stderr, Name ": level of %s changed to %s\n",
                                devname, c);    
-               orig_level = info->array.level;
+               orig_level = array.level;
                sysfs_freeze_array(info);
 
                if (reshape.level > 0 && st->ss->external) {
@@ -1754,7 +1782,7 @@ static int reshape_array(char *container, int fd, char *devname,
                 */
                /* read current array info */
                if (ioctl(fd, GET_ARRAY_INFO, &array) != 0) {
-                       dprintf("Canot get array information.\n");
+                       dprintf("Cannot get array information.\n");
                        goto release;
                }
                /* compare current array info with new values and if
@@ -3345,10 +3373,22 @@ int Grow_continue(int mdfd, struct supertype *st, struct mdinfo *info,
                fmt_devname(buf, st->container_dev);
                container = buf;
                freeze(st);
-               if (info->reshape_active == 2)
+
+               if (!mdmon_running(st->container_dev))
+                       start_mdmon(st->container_dev);
+               ping_monitor(devnum2devname(st->container_dev));
+
+
+               if (info->reshape_active == 2) {
+                       int cfd = open_dev(st->container_dev);
+                       if (cfd < 0)
+                               return 1;
+                       st->ss->load_container(st, cfd, container);
+                       close(cfd);
                        return reshape_container(container, NULL,
                                                 st, info, 0, backup_file,
                                                 0, 1);
+               }
        }
        return reshape_array(container, mdfd, "array", st, info, 1,
                             backup_file, 0, 0, 1);