summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2015-07-06 13:45:39 +1000
committerNeilBrown <neilb@suse.de>2015-07-06 13:45:39 +1000
commite3e0d0a8436f3dc79b7c80d02724467de6c2f7ab (patch)
treea5c4d9d14002beb613fa4e611fa5d5abe8b74edc
parent932be6276ee6a28ef64f11b260e0c9d3cafd6d4c (diff)
downloadmdadm-e3e0d0a8436f3dc79b7c80d02724467de6c2f7ab.tar.gz
Manage/stop: don't stop during initial critical section.
If the array is reshaping to more devices, then stopping during that initial critical section is a bad idea. So check for it and wait a bit. Should probably handle final critical section of a reduction too. same-size reshape should be handled correctly already. Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r--Manage.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/Manage.c b/Manage.c
index 3930f4f..47faeed 100644
--- a/Manage.c
+++ b/Manage.c
@@ -344,9 +344,7 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry)
sysfs_attribute_available(mdi, NULL, "reshape_direction") &&
sysfs_get_str(mdi, NULL, "sync_action", buf, 20) > 0 &&
strcmp(buf, "reshape\n") == 0 &&
- sysfs_get_two(mdi, NULL, "raid_disks", &rd1, &rd2) == 2 &&
- sysfs_set_str(mdi, NULL, "sync_action", "frozen") == 0) {
- /* Array is frozen */
+ sysfs_get_two(mdi, NULL, "raid_disks", &rd1, &rd2) == 2) {
unsigned long long position, curr;
unsigned long long chunk1, chunk2;
unsigned long long rddiv, chunkdiv;
@@ -357,12 +355,28 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry)
int delay;
int scfd;
+ delay = 40;
+ while (rd1 > rd2 && delay > 0 &&
+ sysfs_get_ll(mdi, NULL, "sync_max", &old_sync_max) == 0) {
+ /* must be in the critical section - wait a bit */
+ delay -= 1;
+ usleep(100000);
+ }
+
+ if (sysfs_set_str(mdi, NULL, "sync_action", "frozen") != 0)
+ goto done;
+ /* Array is frozen */
+
rd1 -= mdi->array.level == 6 ? 2 : 1;
rd2 -= mdi->array.level == 6 ? 2 : 1;
sysfs_get_str(mdi, NULL, "reshape_direction", buf, sizeof(buf));
if (strncmp(buf, "back", 4) == 0)
backwards = 1;
- sysfs_get_ll(mdi, NULL, "reshape_position", &position);
+ if (sysfs_get_ll(mdi, NULL, "reshape_position", &position) != 0) {
+ /* reshape must have finished now */
+ sysfs_set_str(mdi, NULL, "sync_action", "idle");
+ goto done;
+ }
sysfs_get_two(mdi, NULL, "chunk_size", &chunk1, &chunk2);
chunk1 /= 512;
chunk2 /= 512;
@@ -456,6 +470,7 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry)
close(scfd);
}
+done:
/* As we have an O_EXCL open, any use of the device
* which blocks STOP_ARRAY is probably a transient use,