Stop managed arrays more carefully.
authorNeil Brown <neilb@suse.de>
Fri, 18 Jul 2008 06:37:09 +0000 (16:37 +1000)
committerNeil Brown <neilb@suse.de>
Fri, 18 Jul 2008 06:37:09 +0000 (16:37 +1000)
If an array is being managed by mdmon, then just
write "inactive" to stop it, and let mdmon do the
final "clear".  This makes sure mdmon has a chance
to read the final state and update the metadata properly.

After writing "inactive" with use "ping_monitor" to synchronise
with mdadm, then STOP the array just in case it is still running,
else we will get into an infinite loop in "mdadm -Ss".

Signed-off-by: Neil Brown <neilb@suse.de>
Manage.c
mdadm.c

index 90b5889..0c6b59c 100644 (file)
--- a/Manage.c
+++ b/Manage.c
@@ -111,15 +111,49 @@ int Manage_runstop(char *devname, int fd, int runstop, int quiet)
        } else if (runstop < 0){
                struct map_ent *map = NULL;
                struct stat stb;
-               if (ioctl(fd, STOP_ARRAY, NULL)) {
+               struct mdinfo *mdi;
+               /* If this is an mdmon managed array, just write 'inactive'
+                * to the array state and let mdmon clear up.
+                */
+               mdi = sysfs_read(fd, -1, GET_LEVEL|GET_VERSION);
+               if (mdi &&
+                   mdi->array.level > 0 &&
+                   mdi->text_version[0] == '/') {
+                       char *cp;
+
+                       /* This is mdmon managed. */
+                       close(fd);
+                       if (sysfs_set_str(mdi, NULL,
+                                         "array_state", "inactive") < 0) {
+                               if (quiet==0)
+                                       fprintf(stderr, Name
+                                               ": fail to stop array %s: %s\n",
+                                               devname, strerror(errno));
+                               return 1;
+                       }
+
+                       /* Give monitor a chance to act */
+                       cp = strchr(mdi->text_version+1, '/');
+                       if (*cp)
+                               *cp = 0;
+                       ping_monitor(mdi->text_version+1);
+
+                       fd = open(devname, O_RDONLY);
+               }
+               if (mdi)
+                       sysfs_free(mdi);
+
+               if (fd >= 0 && ioctl(fd, STOP_ARRAY, NULL)) {
                        if (quiet==0)
-                               fprintf(stderr, Name ": fail to stop array %s: %s\n",
+                               fprintf(stderr, Name
+                                       ": fail to stop array %s: %s\n",
                                        devname, strerror(errno));
                        return 1;
                }
+
                if (quiet <= 0)
                        fprintf(stderr, Name ": stopped %s\n", devname);
-               if (fstat(fd, &stb) == 0) {
+               if (fd >= 0 && fstat(fd, &stb) == 0) {
                        int devnum;
                        if (major(stb.st_rdev) == MD_MAJOR)
                                devnum = minor(stb.st_rdev);
diff --git a/mdadm.c b/mdadm.c
index 6fe6b99..8b4b5df 100644 (file)
--- a/mdadm.c
+++ b/mdadm.c
@@ -1257,16 +1257,6 @@ int main(int argc, char *argv[])
 
                                                        put_md_name(name);
                                                }
-                                               /* This is a bit of a hack.
-                                                * When we stop an array in a container, it
-                                                * takes a moment for mdmon to let go.
-                                                * So just pause briefly incase that is
-                                                * happening.  Maybe we should do something
-                                                * more deterministic via the socket.
-                                                */
-                                               if (progress && err)
-                                                       usleep(50000);
-
                                        } while (!last && err);
                                        if (err) rv |= 1;
                                } else {