diff options
author | NeilBrown <neilb@suse.de> | 2015-07-06 13:45:39 +1000 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2015-07-06 13:45:39 +1000 |
commit | e3e0d0a8436f3dc79b7c80d02724467de6c2f7ab (patch) | |
tree | a5c4d9d14002beb613fa4e611fa5d5abe8b74edc | |
parent | 932be6276ee6a28ef64f11b260e0c9d3cafd6d4c (diff) | |
download | mdadm-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.c | 23 |
1 files changed, 19 insertions, 4 deletions
@@ -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, |