]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Fix some issues with setting 'new' state of a reshape
authorNeilBrown <neilb@suse.de>
Tue, 25 Jan 2011 22:47:06 +0000 (08:47 +1000)
committerNeilBrown <neilb@suse.de>
Tue, 25 Jan 2011 22:50:28 +0000 (08:50 +1000)
- when reshaping a container, ->reshape_active is already set
  even though it isn't really active yet, so we need to set
  the new geometry even when reshape_active is set.  This is safe.

- When restarting a reshape, make sure the reshape_position is set
  appropriately when external metadata is used.

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

diff --git a/Grow.c b/Grow.c
index d0df6bd59650d10ea9155834cb0a94372643273f..42ef17ce9f8ecef895dcb4bea84e2a7791911538 100644 (file)
--- a/Grow.c
+++ b/Grow.c
@@ -1868,19 +1868,23 @@ started:
 
        sra->new_chunk = info->new_chunk;
 
-       sra->reshape_progress = 0;
-       if (reshape.after.data_disks < reshape.before.data_disks)
-               /* start from the end of the new array */
-               sra->reshape_progress = (sra->component_size
-                                        * reshape.after.data_disks);
-       
        if (info->reshape_active)
                sra->reshape_progress = info->reshape_progress;
-       else if (info->array.chunk_size == info->new_chunk &&
+       else {
+               sra->reshape_progress = 0;
+               if (reshape.after.data_disks < reshape.before.data_disks)
+                       /* start from the end of the new array */
+                       sra->reshape_progress = (sra->component_size
+                                                * reshape.after.data_disks);
+       }
+
+       if (info->array.chunk_size == info->new_chunk &&
            reshape.before.layout == reshape.after.layout &&
            st->ss->external == 0) {
+               /* use SET_ARRAY_INFO but only if reshape hasn't started */
                array.raid_disks = reshape.after.data_disks + reshape.parity;
-               if (ioctl(fd, SET_ARRAY_INFO, &array) != 0) {
+               if (!info->reshape_active &&
+                   ioctl(fd, SET_ARRAY_INFO, &array) != 0) {
                        int err = errno;
 
                        fprintf(stderr,
@@ -1897,7 +1901,10 @@ started:
                }
        } else {
                /* set them all just in case some old 'new_*' value
-                * persists from some earlier problem
+                * persists from some earlier problem.
+                * We even set them when restarting in the middle.  They will
+                * already be set in that case so this will be a no-op,
+                * but it is hard to tell the difference.
                 */
                int err = 0;
                if (sysfs_set_num(sra, NULL, "chunk_size", info->new_chunk) < 0)
diff --git a/sysfs.c b/sysfs.c
index a9ece82b672d03c87cb35cbb34dfeb1f100fb08a..f0773d476611fa8e66682ed770d0141de22e4263 100644 (file)
--- a/sysfs.c
+++ b/sysfs.c
@@ -569,6 +569,15 @@ int sysfs_set_array(struct mdinfo *info, int vers)
 
        if (info->array.level > 0)
                rv |= sysfs_set_num(info, NULL, "resync_start", info->resync_start);
+
+       if (info->reshape_active) {
+               rv |= sysfs_set_num(info, NULL, "reshape_position",
+                                   info->reshape_progress);
+               rv |= sysfs_set_num(info, NULL, "chunk_size", info->new_chunk);
+               /* Don't set layout or raid_disks here as they require some
+                * analysis and are set by reshape_array 
+                */
+       }
        return rv;
 }