]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
super1: allow reshape that hasn't really started to be reverted.
authorNeilBrown <neilb@suse.com>
Thu, 28 Jan 2016 01:57:08 +0000 (12:57 +1100)
committerNeilBrown <neilb@suse.com>
Thu, 28 Jan 2016 01:57:08 +0000 (12:57 +1100)
A simple revert doesn't work here because the reshape_position is
in the critical section.
The best approach is to let the reshape progress a bit and then
go backwards.
If that isn't possible, assembling with --update=revert-reshape and
--invalid-backup should work.

Reported-by-tested-by: George Rapp <george.rapp@gmail.com>
Signed-off-by: NeilBrown <neilb@suse.com>
Assemble.c
super1.c

index a7cd16386d4bc641f6c6484c7280d0d8ae509fe6..25a14be4fcfe07af91bd4587ad974b5a06ad2be9 100644 (file)
@@ -643,7 +643,14 @@ static int load_devices(struct devs *devices, char *devmap,
                        } else if (strcmp(c->update, "nodes") == 0) {
                                tst->nodes = c->nodes;
                                err = tst->ss->write_bitmap(tst, dfd, NodeNumUpdate);
-                       } else
+                       } else if (strcmp(c->update, "revert-reshape") == 0 &&
+                                  c->invalid_backup)
+                               err = tst->ss->update_super(tst, content,
+                                                           "revert-reshape-nobackup",
+                                                           devname, c->verbose,
+                                                           ident->uuid_set,
+                                                           c->homehost);
+                       else
                                err = tst->ss->update_super(tst, content, c->update,
                                                            devname, c->verbose,
                                                            ident->uuid_set,
index 5d08d4de8155e217091ac228af8ab087c2c94418..0f6797a8f1cdb3d5e351be20bd7ff3f4f095d558 100644 (file)
--- a/super1.c
+++ b/super1.c
@@ -1307,7 +1307,7 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
                        (st->sb + MAX_SB_SIZE + BM_SUPER_SIZE);
                sb->data_size = __cpu_to_le64(
                        misc->device_size - __le64_to_cpu(sb->data_offset));
-       } else if (strcmp(update, "revert-reshape") == 0) {
+       } else if (strncmp(update, "revert-reshape", 14) == 0) {
                rv = -2;
                if (!(sb->feature_map & __cpu_to_le32(MD_FEATURE_RESHAPE_ACTIVE)))
                        pr_err("No active reshape to revert on %s\n",
@@ -1317,6 +1317,24 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
                        unsigned long long reshape_sectors;
                        long reshape_chunk;
                        rv = 0;
+                       /* If the reshape hasn't started, just stop it.
+                        * It is conceivable that a stripe was modified but
+                        * the metadata not updated.  In that case the backup
+                        * should have been used to get passed the critical stage.
+                        * If that couldn't happen, the "-nobackup" version
+                        * will be used.
+                        */
+                       if (strcmp(update, "revert-reshape-nobackup") == 0 &&
+                           sb->reshape_position == 0 &&
+                           (__le32_to_cpu(sb->delta_disks) > 0 ||
+                            (__le32_to_cpu(sb->delta_disks) == 0 &&
+                             !(sb->feature_map & __cpu_to_le32(MD_FEATURE_RESHAPE_BACKWARDS))))) {
+                               sb->feature_map &= ~__cpu_to_le32(MD_FEATURE_RESHAPE_ACTIVE);
+                               sb->raid_disks = __cpu_to_le32(__le32_to_cpu(sb->raid_disks) -
+                                                              __le32_to_cpu(sb->delta_disks));
+                               sb->delta_disks = 0;
+                               goto done;
+                       }
                        /* reshape_position is a little messy.
                         * Its value must be a multiple of the larger
                         * chunk size, and of the "after" data disks.
@@ -1363,6 +1381,7 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
                                sb->new_offset = __cpu_to_le32(-offset_delta);
                                sb->data_size = __cpu_to_le64(__le64_to_cpu(sb->data_size) - offset_delta);
                        }
+               done:;
                }
        } else if (strcmp(update, "_reshape_progress")==0)
                sb->reshape_position = __cpu_to_le64(info->reshape_progress);