]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Retry --stop --scan until all stoppable devices have been stopped
authorNeil Brown <neilb@suse.de>
Tue, 14 Jun 2005 06:32:18 +0000 (06:32 +0000)
committerNeil Brown <neilb@suse.de>
Tue, 14 Jun 2005 06:32:18 +0000 (06:32 +0000)
This is needed to reliably stop stacked arrays

Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
ChangeLog
Create.c
Manage.c
mdadm.c
mdadm.h

index c5780d967a2f32e70770c0c2a5b7f18faa55935e..38e6758b4475c981ad82b956c181c69b37320c90 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,8 @@ Changes Prior to this release
     -   Don't use 'lstat' to check for blockdevices, use stat.
     -   Document --size=max option for --grow
     -   Document SparesMissing event and DeviceDisappeared/WrongLevel
+    -   --stop --scan repeatly cycles until no more progress can be made
+       so that stack devices are stopped properly
        
 Changes Prior to 1.11.0 release
     -   Fix embarassing bug which causes --add to always fail.
index 20ef6bf1dffb96880ba4ad9ecce362c160095d8f..735b8d799a858ae3d69f66acf8a88c53b91e0de0 100644 (file)
--- a/Create.c
+++ b/Create.c
@@ -464,7 +464,7 @@ int Create(struct supertype *st, char *mddev, int mdfd,
                if (ioctl(mdfd, RUN_ARRAY, &param)) {
                        fprintf(stderr, Name ": RUN_ARRAY failed: %s\n",
                                strerror(errno));
-                       Manage_runstop(mddev, mdfd, -1);
+                       Manage_runstop(mddev, mdfd, -1, 0);
                        return 1;
                }
                fprintf(stderr, Name ": array %s started.\n", mddev);
index 2806201afcabbb38dc50ccb55b670cb594614d65..a9e895626357c18d222cc014900102371f0a8253 100644 (file)
--- a/Manage.c
+++ b/Manage.c
@@ -72,7 +72,7 @@ int Manage_ro(char *devname, int fd, int readonly)
        return 0;                       
 }
 
-int Manage_runstop(char *devname, int fd, int runstop)
+int Manage_runstop(char *devname, int fd, int runstop, int quiet)
 {
        /* Run or stop the array. array must already be configured
         * required >= 0.90.0
@@ -81,8 +81,8 @@ int Manage_runstop(char *devname, int fd, int runstop)
 
        if (runstop == -1 && md_get_version(fd) < 9000) {
                if (ioctl(fd, STOP_MD, 0)) {
-                       fprintf(stderr, Name ": stopping device %s failed: %s\n",
-                               devname, strerror(errno));
+                       if (!quiet) fprintf(stderr, Name ": stopping device %s failed: %s\n",
+                                           devname, strerror(errno));
                        return 1;
                }
        }
@@ -106,8 +106,9 @@ int Manage_runstop(char *devname, int fd, int runstop)
                }
        } else if (runstop < 0){
                if (ioctl(fd, STOP_ARRAY, NULL)) {
-                       fprintf(stderr, Name ": fail to stop array %s: %s\n",
-                               devname, strerror(errno));
+                       if (!quiet)
+                               fprintf(stderr, Name ": fail to stop array %s: %s\n",
+                                       devname, strerror(errno));
                        return 1;
                }
        }
diff --git a/mdadm.c b/mdadm.c
index e8e8ed375d91e6bc9199ccfd32851599ba33fb90..6d0548ecaf0bc93240883401ac1c69ea0a15ca94 100644 (file)
--- a/mdadm.c
+++ b/mdadm.c
@@ -809,7 +809,7 @@ int main(int argc, char *argv[])
                if (!rv && readonly < 0)
                        rv = Manage_ro(devlist->devname, mdfd, readonly);
                if (!rv && runstop)
-                       rv = Manage_runstop(devlist->devname, mdfd, runstop);
+                       rv = Manage_runstop(devlist->devname, mdfd, runstop, 0);
                break;
        case ASSEMBLE:
                if (devs_found == 1 && ident.uuid_set == 0 &&
@@ -939,20 +939,10 @@ int main(int argc, char *argv[])
                        rv = Examine(devlist, scan?!verbose:brief, scan, SparcAdjust, ss);
                } else {
                        if (devlist == NULL) {
-                               if ((devmode == 'S' ||devmode=='D') && scan) {
-                                       /* apply to all devices in /proc/mdstat */
+                               if (devmode=='D' && scan) {
+                                       /* apply --detail to all devices in /proc/mdstat */
                                        struct mdstat_ent *ms = mdstat_read(0);
                                        struct mdstat_ent *e;
-                                       if (devmode == 'S') {
-                                               /* reverse order so that arrays made of arrays are stopped properly */
-                                               struct mdstat_ent *sm = NULL;
-                                               while ((e=ms) != NULL) {
-                                                       ms = e->next;
-                                                       e->next = sm;
-                                                       sm = e;
-                                               }
-                                               ms = sm;
-                                       }
                                        for (e=ms ; e ; e=e->next) {
                                                char *name = get_md_name(e->devnum);
 
@@ -961,18 +951,43 @@ int main(int argc, char *argv[])
                                                                e->dev);
                                                        continue;
                                                }
-                                               if (devmode == 'D')
-                                                       rv |= Detail(name, !verbose, test);
-                                               else if (devmode=='S') {
+                                               rv |= Detail(name, !verbose, test);
+                                               put_md_name(name);
+                                       }
+                               } else  if (devmode == 'S' && scan) {
+                                       /* apply --stop to all devices in /proc/mdstat */
+                                       /* Due to possible stacking of devices, repeat until
+                                        * nothing more can be stopped
+                                        */
+                                       int progress=1, err;
+                                       int last = 0;
+                                       do {
+                                               struct mdstat_ent *ms = mdstat_read(0);
+                                               struct mdstat_ent *e;
+
+                                               if (!progress) last = 1;
+                                               progress = 0; err = 0;
+                                               for (e=ms ; e ; e=e->next) {
+                                                       char *name = get_md_name(e->devnum);
+
+                                                       if (!name) {
+                                                               fprintf(stderr, Name ": cannot find device file for %s\n",
+                                                                       e->dev);
+                                                               continue;
+                                                       }
                                                        mdfd = open_mddev(name, 0);
                                                        if (mdfd >= 0) {
-                                                               rv |= Manage_runstop(name, mdfd, -1);
+                                                               if (Manage_runstop(name, mdfd, -1, !last))
+                                                                       err = 1;
+                                                               else
+                                                                       progress = 1;
                                                                close(mdfd);
                                                        }
+
+                                                       put_md_name(name);
                                                }
-                                               put_md_name(name);
-                                       }
-                               } else {                                                
+                                       } while (!last && err);
+                               } else {
                                        fprintf(stderr, Name ": No devices given.\n");
                                        exit(2);
                                }
@@ -992,9 +1007,9 @@ int main(int argc, char *argv[])
                                if (mdfd>=0) {
                                        switch(dv->disposition) {
                                        case 'R':
-                                               rv |= Manage_runstop(dv->devname, mdfd, 1); break;
+                                               rv |= Manage_runstop(dv->devname, mdfd, 1, 0); break;
                                        case 'S':
-                                               rv |= Manage_runstop(dv->devname, mdfd, -1); break;
+                                               rv |= Manage_runstop(dv->devname, mdfd, -1, 0); break;
                                        case 'o':
                                                rv |= Manage_ro(dv->devname, mdfd, 1); break;
                                        case 'w':
diff --git a/mdadm.h b/mdadm.h
index 877f353aaa24e526cc90e98e1e362cbb240bbbeb..7a901c711d702143d8b6ff735685746d3e6f975b 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -202,7 +202,7 @@ extern struct supertype *guess_super(int fd);
 
 
 extern int Manage_ro(char *devname, int fd, int readonly);
-extern int Manage_runstop(char *devname, int fd, int runstop);
+extern int Manage_runstop(char *devname, int fd, int runstop, int quiet);
 extern int Manage_resize(char *devname, int fd, long long size, int raid_disks);
 extern int Manage_reconfig(char *devname, int fd, int layout);
 extern int Manage_subdevs(char *devname, int fd,