]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Manage/stop: don't stop during initial critical section.
authorNeilBrown <neilb@suse.de>
Mon, 6 Jul 2015 03:45:39 +0000 (13:45 +1000)
committerNeilBrown <neilb@suse.de>
Mon, 6 Jul 2015 03:45:39 +0000 (13:45 +1000)
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>
Manage.c

index 3930f4fd7ad652927cab16b3cdeef8d4a1ad6487..47faeedb7da4deb36ddedae6e494694359f9d8c2 100644 (file)
--- 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,