]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Grow: support reshape of RAID0 arrays.
authorNeilBrown <neilb@suse.de>
Thu, 10 Mar 2011 04:05:23 +0000 (15:05 +1100)
committerNeilBrown <neilb@suse.de>
Thu, 10 Mar 2011 04:05:23 +0000 (15:05 +1100)
This is done via conversion to RAID4 and back.

To grow the array, extra devices will be needed which cannot
already be present as spares - so allow a list of new devices
to be included in grow request which changed the number of devices.

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

diff --git a/Grow.c b/Grow.c
index 812c1da9e997c3c0f3dda704f98e55e7e5f8ecdf..2a414289d864ef05840e62ccf9f16324af295096 100644 (file)
--- a/Grow.c
+++ b/Grow.c
@@ -1273,7 +1273,8 @@ char *analyse_change(struct mdinfo *info, struct reshape *re)
 
 static int reshape_array(char *container, int fd, char *devname,
                         struct supertype *st, struct mdinfo *info,
-                        int force, char *backup_file, int quiet, int forked,
+                        int force, struct mddev_dev *devlist,
+                        char *backup_file, int quiet, int forked,
                         int restart);
 static int reshape_container(char *container, char *devname,
                             struct supertype *st, 
@@ -1285,6 +1286,7 @@ static int reshape_container(char *container, char *devname,
 int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
                 long long size,
                 int level, char *layout_str, int chunksize, int raid_disks,
+                struct mddev_dev *devlist,
                 int force)
 {
        /* Make some changes in the shape of an array.
@@ -1315,6 +1317,9 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
        char container_buf[20];
        int cfd = -1;
 
+       struct mddev_dev *dv;
+       int added_disks;
+
        struct mdinfo info;
        struct mdinfo *sra;
 
@@ -1390,10 +1395,13 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
 
                if (mdmon_running(container_dev))
                        st->update_tail = &st->updates;
-       } 
+       }
 
+       added_disks = 0;
+       for (dv = devlist; dv; dv = dv->next)
+               added_disks++;
        if (raid_disks > array.raid_disks &&
-           array.spare_disks < (raid_disks - array.raid_disks) &&
+           array.spare_disks +added_disks < (raid_disks - array.raid_disks) &&
            !force) {
                fprintf(stderr,
                        Name ": Need %d spare%s to avoid degraded array,"
@@ -1401,7 +1409,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
                        "       Use --force to over-ride this check.\n",
                        raid_disks - array.raid_disks, 
                        raid_disks - array.raid_disks == 1 ? "" : "s", 
-                       array.spare_disks);
+                       array.spare_disks + added_disks);
                return 1;
        }
 
@@ -1614,7 +1622,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
                }
                sync_metadata(st);
                rv = reshape_array(container, fd, devname, st, &info, force,
-                                  backup_file, quiet, 0, 0);
+                                  devlist, backup_file, quiet, 0, 0);
                frozen = 0;
        }
 release:
@@ -1625,7 +1633,7 @@ release:
 
 static int reshape_array(char *container, int fd, char *devname,
                         struct supertype *st, struct mdinfo *info,
-                        int force,
+                        int force, struct mddev_dev *devlist,
                         char *backup_file, int quiet, int forked,
                         int restart)
 {
@@ -1638,6 +1646,9 @@ static int reshape_array(char *container, int fd, char *devname,
        struct mdu_array_info_s array;
        char *c;
 
+       struct mddev_dev *dv;
+       int added_disks;
+
        int *fdlist;
        unsigned long long *offsets;
        int d;
@@ -1697,20 +1708,23 @@ static int reshape_array(char *container, int fd, char *devname,
         */
        sysfs_freeze_array(info);
        /* Check we have enough spares to not be degraded */
+       added_disks = 0;
+       for (dv = devlist; dv ; dv=dv->next)
+               added_disks++;
        spares_needed = max(reshape.before.data_disks,
                            reshape.after.data_disks)
                + reshape.parity - array.raid_disks;
 
        if (!force &&
-           info->new_level > 1 &&
-           spares_needed > info->array.spare_disks) {
+           info->new_level > 1 && info->array.level > 1 &&
+           spares_needed > info->array.spare_disks + added_disks) {
                fprintf(stderr,
                        Name ": Need %d spare%s to avoid degraded array,"
                        " and only have %d.\n"
                        "       Use --force to over-ride this check.\n",
                        spares_needed,
                        spares_needed == 1 ? "" : "s", 
-                       info->array.spare_disks);
+                       info->array.spare_disks + added_disks);
                goto release;
        }
        /* Check we have enough spares to not fail */
@@ -1718,13 +1732,13 @@ static int reshape_array(char *container, int fd, char *devname,
                            reshape.after.data_disks)
                - array.raid_disks;
        if ((info->new_level > 1 || info->new_level == 0) &&
-           spares_needed > info->array.spare_disks) {
+           spares_needed > info->array.spare_disks +added_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);
+                       info->array.spare_disks + added_disks);
                goto release;
        }
 
@@ -1783,6 +1797,13 @@ static int reshape_array(char *container, int fd, char *devname,
                        sysfs_free(info2);
                }
        }
+       /* We might have been given some devices to add to the
+        * array.  Now that the array has been changed to the right
+        * level and frozen, we can safely add them.
+        */
+       if (devlist)
+               Manage_subdevs(devname, fd, devlist, !quiet,
+                              0,NULL);
 
        if (reshape.backup_blocks == 0) {
                /* No restriping needed, but we might need to impose
@@ -2263,7 +2284,7 @@ int reshape_container(char *container, char *devname,
                sysfs_init(content, fd, mdstat->devnum);
 
                rv = reshape_array(container, fd, adev, st,
-                                  content, force,
+                                  content, force, NULL,
                                   backup_file, quiet, 1, restart);
                close(fd);
                restart = 0;
@@ -3399,5 +3420,5 @@ int Grow_continue(int mdfd, struct supertype *st, struct mdinfo *info,
                }
        }
        return reshape_array(container, mdfd, "array", st, info, 1,
-                            backup_file, 0, 0, 1);
+                            NULL, backup_file, 0, 0, 1);
 }
diff --git a/mdadm.c b/mdadm.c
index 443c88a769b0405cc6cfcaaed31dc71fc1ad6969..c44c43228067c536eeccd18d2480310bc0dac444 100644 (file)
--- a/mdadm.c
+++ b/mdadm.c
@@ -1630,22 +1630,26 @@ int main(int argc, char *argv[])
                                break;
                        }
                }
-               if (devs_found > 1) {
-
+               if (devs_found > 1 && raiddisks == 0) {
                        /* must be '-a'. */
-                       if (size >= 0 || raiddisks || chunk || layout_str != NULL || bitmap_file) {
-                               fprintf(stderr, Name ": --add cannot be used with other geometry changes in --grow mode\n");
+                       if (size >= 0 || chunk || layout_str != NULL || bitmap_file) {
+                               fprintf(stderr, Name ": --add cannot be used with "
+                                       "other geometry changes in --grow mode\n");
                                rv = 1;
                                break;
                        }
                        for (dv=devlist->next; dv ; dv=dv->next) {
-                               rv = Grow_Add_device(devlist->devname, mdfd, dv->devname);
+                               rv = Grow_Add_device(devlist->devname, mdfd,
+                                                    dv->devname);
                                if (rv)
                                        break;
                        }
                } else if (bitmap_file) {
-                       if (size >= 0 || raiddisks || chunk || layout_str != NULL) {
-                               fprintf(stderr, Name ": --bitmap changes cannot be used with other geometry changes in --grow mode\n");
+                       if (size >= 0 || raiddisks || chunk ||
+                           layout_str != NULL || devs_found) {
+                               fprintf(stderr, Name ": --bitmap changes cannot be "
+                                       "used with other geometry changes "
+                                       "in --grow mode\n");
                                rv = 1;
                                break;
                        }
@@ -1657,6 +1661,7 @@ int main(int argc, char *argv[])
                           || chunk != 0 || level != UnSet) {
                        rv = Grow_reshape(devlist->devname, mdfd, quiet, backup_file,
                                          size, level, layout_str, chunk, raiddisks,
+                                         devlist->next,
                                          force);
                } else if (array_size < 0)
                        fprintf(stderr, Name ": no changes to --grow\n");
diff --git a/mdadm.h b/mdadm.h
index db151753aed99a0dc4d7710f6036b14da29cc92c..fa84ad2719308e81e92757c4a6ead8848754088a 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -1008,6 +1008,7 @@ extern int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int dela
 extern int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
                        long long size,
                        int level, char *layout_str, int chunksize, int raid_disks,
+                       struct mddev_dev *devlist,
                        int force);
 extern int Grow_restart(struct supertype *st, struct mdinfo *info,
                        int *fdlist, int cnt, char *backup_file, int verbose);