summaryrefslogtreecommitdiff
path: root/super1.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.com>2016-01-28 12:57:08 +1100
committerNeilBrown <neilb@suse.com>2016-01-28 12:57:08 +1100
commitd5ff855d477cea9c8f242721923982aeb81a6dbc (patch)
treedb7c1d07c43349b142745829eb0df5dfbcbd661c /super1.c
parent9f7f28ee5030bbed94c4d54a8da908649ccb7ce0 (diff)
downloadmdadm-d5ff855d477cea9c8f242721923982aeb81a6dbc.tar.gz
super1: allow reshape that hasn't really started to be reverted.
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>
Diffstat (limited to 'super1.c')
-rw-r--r--super1.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/super1.c b/super1.c
index 5d08d4d..0f6797a 100644
--- 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);