]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Retry --stop --scan until all stoppable devices have been stopped
authorNeil Brown <neilb@suse.de>
Wed, 8 Jun 2005 00:28:15 +0000 (00:28 +0000)
committerNeil Brown <neilb@suse.de>
Wed, 8 Jun 2005 00:28:15 +0000 (00:28 +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 12e94ef869e976ab4421928fde9ea243c91ae6d7..03364e9371541ac1c4ed624b02606a0b0a00ca08 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,6 +3,8 @@ Changes Prior to 1.12.0 release
     -   Get size calculation right when in Create when BLKGESIZE64 not available
     -   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 09adc99a668dc61a123f6c89d667e179e4e4c817..2a6c5a2920b30dca9a6a207e384d73b1cf139b6a 100644 (file)
--- a/Create.c
+++ b/Create.c
@@ -393,7 +393,7 @@ int Create(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 c1debfa97f9ba9ca7e6af8ed019fb72f30e273c5..96904c1f525839bb227f9f21a43fb344465e15a0 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 daf24123ab40d430a71540da078170001b92fbc9..57fd3cdcb7190eeaa15a7483c89dcddf8dbde55d 100644 (file)
--- a/mdadm.c
+++ b/mdadm.c
@@ -720,7 +720,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 &&
@@ -818,20 +818,10 @@ int main(int argc, char *argv[])
                        rv = Examine(devlist, scan?!verbose:brief, scan, SparcAdjust);
                } 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);
 
@@ -840,18 +830,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);
                                }
@@ -869,9 +884,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 b7f34d10b074a916e4cd4cc2a2d55184c402518b..f69695cd5ee617bf7bdbedc26957c0b6a9ec21da 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -156,7 +156,7 @@ extern char *map_dev(int major, int minor);
 
 
 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,