]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - mdadm.c
Support fixing of byte-swapped superblocks.
[thirdparty/mdadm.git] / mdadm.c
diff --git a/mdadm.c b/mdadm.c
index e8e8ed375d91e6bc9199ccfd32851599ba33fb90..2b2b9be7043df8e8707c7a6e293d062a09b952c6 100644 (file)
--- a/mdadm.c
+++ b/mdadm.c
@@ -135,7 +135,7 @@ int main(int argc, char *argv[])
                        fputs(Version, stderr);
                        exit(0);
 
-               case 'v': verbose = 1;
+               case 'v': verbose++;
                        continue;
 
                case 'b':
@@ -493,6 +493,7 @@ int main(int argc, char *argv[])
                        continue;
 
                case O(BUILD,'f'): /* force honouring '-n 1' */
+               case O(GROW,'f'): /* ditto */
                case O(CREATE,'f'): /* force honouring of device list */
                case O(ASSEMBLE,'f'): /* force assembly */
                case O(MISC,'f'): /* force zero */
@@ -546,6 +547,20 @@ int main(int argc, char *argv[])
                                continue;
                        if (strcmp(update, "resync")==0)
                                continue;
+                       if (strcmp(update, "byteorder")==0) {
+                               if (ss) {
+                                       fprintf(stderr, Name ": must not set metadata type with --update=byteorder.\n");
+                                       exit(2);
+                               }
+                               for(i=0; !ss && superlist[i]; i++) 
+                                       ss = superlist[i]->match_metadata_desc("0.swap");
+                               if (!ss) {
+                                       fprintf(stderr, Name ": INTERNAL ERROR cannot find 0.swap\n");
+                                       exit(2);
+                               }
+
+                               continue;
+                       }
                        fprintf(stderr, Name ": '--update %s' invalid.  Only 'sparc2.2', 'super-minor', 'resync' or 'summaries' supported\n",update);
                        exit(2);
 
@@ -809,7 +824,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 &&
@@ -821,7 +836,8 @@ int main(int argc, char *argv[])
                                        devlist->devname);
                                rv |= 1;
                        } else {
-                               mdfd = open_mddev(devlist->devname, array_ident->autof);
+                               mdfd = open_mddev(devlist->devname, 
+                                                 array_ident->autof ? array_ident->autof : autof);
                                if (mdfd < 0)
                                        rv |= 1;
                                else {
@@ -848,7 +864,8 @@ int main(int argc, char *argv[])
                                        rv |= 1;
                                        continue;
                                }
-                               mdfd = open_mddev(dv->devname, array_ident->autof);
+                               mdfd = open_mddev(dv->devname, 
+                                                 array_ident->autof ?array_ident->autof : autof);
                                if (mdfd < 0) {
                                        rv |= 1;
                                        continue;
@@ -866,7 +883,8 @@ int main(int argc, char *argv[])
                        } else
                                for (; array_list; array_list = array_list->next) {
                                        mdu_array_info_t array;
-                                       mdfd = open_mddev(array_list->devname, array_list->autof);
+                                       mdfd = open_mddev(array_list->devname, 
+                                                         array_list->autof ? array_list->autof : autof);
                                        if (mdfd < 0) {
                                                rv |= 1;
                                                continue;
@@ -936,23 +954,13 @@ int main(int argc, char *argv[])
                                fprintf(stderr, Name ": No devices listed in %s\n", configfile?configfile:DefaultConfFile);
                                exit(1);
                        }
-                       rv = Examine(devlist, scan?!verbose:brief, scan, SparcAdjust, ss);
+                       rv = Examine(devlist, scan?(verbose>1?0:verbose+1):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 +969,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>1?0:verbose+1, 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);
                                }
@@ -980,7 +1013,7 @@ int main(int argc, char *argv[])
                        for (dv=devlist ; dv; dv=dv->next) {
                                switch(dv->disposition) {
                                case 'D':
-                                       rv |= Detail(dv->devname, brief, test); continue;
+                                       rv |= Detail(dv->devname, brief?1+verbose:0, test); continue;
                                case 'K': /* Zero superblock */
                                        rv |= Kill(dv->devname, force); continue;
                                case 'Q':
@@ -992,9 +1025,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':