]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
External reshape (step 2): Freeze container
authorDan Williams <dan.j.williams@intel.com>
Tue, 23 Nov 2010 05:39:58 +0000 (16:39 +1100)
committerNeilBrown <neilb@suse.de>
Tue, 23 Nov 2010 05:39:58 +0000 (16:39 +1100)
When growing the number of raid disks the reshape process will promote
container-spares to subarray-spares (later the kernel promotes them to
subarray-members in raid5_start_reshape()).  The automatic spare
promotion that mdmon performs upon seeing a degraded array must be
disabled until the reshape process has been initiated.  Otherwise, mdmon
may start a rebuild before the reshape parameters can be specified.

In the external case we arrange for the monitor to be blocked, and
turn off the safemode delay.
Mdmon is updated to check sync_action is not frozen before initiating
recovery.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
Grow.c

diff --git a/Grow.c b/Grow.c
index d6a05f035907036b03c9f4c7bc04e56b217c9a97..ea8f49326c106dd3a74d9234b657b435ffdd8044 100644 (file)
--- a/Grow.c
+++ b/Grow.c
@@ -458,29 +458,80 @@ static int child_same_size(int afd, struct mdinfo *sra, unsigned long blocks,
                           int disks, int chunk, int level, int layout, int data,
                           int dests, int *destfd, unsigned long long *destoffsets);
 
-static int freeze_array(struct mdinfo *sra)
+static int freeze_container(struct supertype *st)
 {
-       /* Try to freeze resync on this array.
+       int container_dev = (st->container_dev != NoMdDev
+                            ? st->container_dev : st->devnum);
+       char *container = devnum2devname(container_dev);
+
+       if (!container) {
+               fprintf(stderr, Name
+                       ": could not determine container name, freeze aborted\n");
+               return -2;
+       }
+
+       if (block_monitor(container, 1)) {
+               fprintf(stderr, Name ": failed to freeze container\n");
+               return -2;
+       }
+
+       return 1;
+}
+
+static void unfreeze_container(struct supertype *st)
+{
+       int container_dev = (st->container_dev != NoMdDev
+                            ? st->container_dev : st->devnum);
+       char *container = devnum2devname(container_dev);
+
+       if (!container) {
+               fprintf(stderr, Name
+                       ": could not determine container name, unfreeze aborted\n");
+               return;
+       }
+
+       unblock_monitor(container, 1);
+}
+
+static int freeze(struct supertype *st)
+{
+       /* Try to freeze resync/rebuild on this array/container.
         * Return -1 if the array is busy,
+        * return -2 container cannot be frozen,
         * return 0 if this kernel doesn't support 'frozen'
         * return 1 if it worked.
         */
-       char buf[20];
-       if (sysfs_get_str(sra, NULL, "sync_action", buf, 20) <= 0)
-               return 0;
-       if (strcmp(buf, "idle\n") != 0 &&
-           strcmp(buf, "frozen\n") != 0)
-               return -1;
-       if (sysfs_set_str(sra, NULL, "sync_action", "frozen") < 0)
-               return 0;
-       return 1;
+       if (st->ss->external)
+               return freeze_container(st);
+       else {
+               struct mdinfo *sra = sysfs_read(-1, st->devnum, GET_VERSION);
+               int err;
+
+               if (!sra)
+                       return -1;
+               err = sysfs_freeze_array(sra);
+               sysfs_free(sra);
+               return err;
+       }
 }
 
-static void unfreeze_array(struct mdinfo *sra, int frozen)
+static void unfreeze(struct supertype *st, int frozen)
 {
        /* If 'frozen' is 1, unfreeze the array */
-       if (frozen > 0)
-               sysfs_set_str(sra, NULL, "sync_action", "idle");
+       if (frozen <= 0)
+               return;
+
+       if (st->ss->external)
+               return unfreeze_container(st);
+       else {
+               struct mdinfo *sra = sysfs_read(-1, st->devnum, GET_VERSION);
+
+               if (sra)
+                       sysfs_set_str(sra, NULL, "sync_action", "idle");
+               else
+                       fprintf(stderr, Name ": failed to unfreeze array\n");
+               sysfs_free(sra);
+       }
 }
 
 static void wait_reshape(struct mdinfo *sra)
@@ -670,38 +721,40 @@ static void revert_container_raid_disks(struct supertype *st, int fd, char *cont
                return;
        }
 
+       if (st->ss->load_container(st, fd, NULL)) {
+               fprintf(stderr, Name
+                       ": failed read metadata while aborting reshape\n");
+               return ;
+       }
+
+
        for (e = ent; e; e = e->next) {
                int level_fixed = 0, disks_fixed = 0;
-               struct mdinfo *sub, prev;
+               struct mdinfo *sub, *prev;
+               char *subarray;
 
                if (!is_container_member(e, container))
                        continue;
 
-               st->ss->free_super(st);
-               sprintf(st->subarray, "%s", to_subarray(e, container));
-               if (st->ss->load_super(st, fd, NULL)) {
-                       fprintf(stderr, Name
-                               ": failed read metadata while aborting reshape\n");
-                       continue;
-               }
-               st->ss->getinfo_super(st, &prev);
+               subarray = to_subarray(e, container);
+               prev = st->ss->container_content(st, subarray);
 
                /* changing level might change raid_disks so we do it
                 * first and then check if raid_disks still needs fixing
                 */
-               if (map_name(pers, e->level) != prev.array.level) {
+               if (map_name(pers, e->level) != prev->array.level) {
                        sub = sysfs_read(-1, e->devnum, GET_VERSION);
                        if (sub &&
-                           !sysfs_set_num(sub, NULL, "level", prev.array.level))
+                           !sysfs_set_num(sub, NULL, "level", prev->array.level))
                                level_fixed = 1;
                        sysfs_free(sub);
                } else
                        level_fixed = 1;
 
                sub = sysfs_read(-1, e->devnum, GET_DISKS);
-               if (sub && sub->array.raid_disks != prev.array.raid_disks) {
+               if (sub && sub->array.raid_disks != prev->array.raid_disks) {
                        if (!subarray_set_num(container, sub, "raid_disks",
-                                             prev.array.raid_disks))
+                                             prev->array.raid_disks))
                                disks_fixed = 1;
                } else if (sub)
                        disks_fixed = 1;
@@ -710,9 +763,11 @@ static void revert_container_raid_disks(struct supertype *st, int fd, char *cont
                if (!disks_fixed || !level_fixed)
                        fprintf(stderr, Name
                                ": failed to restore %s to a %d-disk %s array\n",
-                               e->dev, prev.array.raid_disks,
-                               map_num(pers, prev.array.level));
+                               e->dev, prev->array.raid_disks,
+                               map_num(pers, prev->array.level));
+               free(prev);
        }
+       st->ss->free_super(st);
        free_mdstat(ent);
 }
 
@@ -801,6 +856,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
         */
        if (st->ss->external) {
                int container_dev;
+               int rv;
 
                if (subarray) {
                        container_dev = st->container_dev;
@@ -820,18 +876,25 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
                if (cfd < 0) {
                        fprintf(stderr, Name ": Unable to open container for %s\n",
                                devname);
+                       free(subarray);
                        return 1;
                }
 
                container = devnum2devname(st->devnum);
                if (!container) {
                        fprintf(stderr, Name ": Could not determine container name\n");
+                       free(subarray);
                        return 1;
                }
 
-               if (st->ss->load_super(st, cfd, NULL)) {
+               if (subarray)
+                       rv = st->ss->load_container(st, cfd, NULL);
+               else
+                       rv = st->ss->load_super(st, cfd, NULL);
+               if (rv) {
                        fprintf(stderr, Name ": Cannot read superblock for %s\n",
                                devname);
+                       free(subarray);
                        return 1;
                }
 
@@ -841,23 +904,25 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
 
        sra = sysfs_read(fd, 0, GET_LEVEL);
        if (sra) {
-               if (st->ss->external && st->subarray[0] == 0) {
+               if (st->ss->external && subarray == NULL) {
                        array.level = LEVEL_CONTAINER;
                        sra->array.level = LEVEL_CONTAINER;
                }
-               frozen = freeze_array(sra);
        } else {
                fprintf(stderr, Name ": failed to read sysfs parameters for %s\n",
                        devname);
                return 1;
        }
-       if (frozen < 0) {
+       frozen = freeze(st);
+       if (frozen < -1) {
+               /* freeze() already spewed the reason */
+               return 1;
+       } else if (frozen < 0) {
                fprintf(stderr, Name ": %s is performing resync/recovery and cannot"
                        " be reshaped\n", devname);
                return 1;
        }
 
-
        /* ========= set size =============== */
        if (size >= 0 && (size == 0 || size != array.size)) {
                long long orig_size = array.size;
@@ -1642,8 +1707,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
                if (c && sysfs_set_str(sra, NULL, "level", c) == 0)
                        fprintf(stderr, Name ": aborting level change\n");
        }
-       if (sra)
-               unfreeze_array(sra, frozen);
+       unfreeze(st, frozen);
        return rv;
 }