]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - mdadm.c
main: split scan_assemble into a separate function
[thirdparty/mdadm.git] / mdadm.c
diff --git a/mdadm.c b/mdadm.c
index 1efa3e80a2eb40292f9379eb0270b17bc1584f4d..082605095a837bacb31c701bcddeda4dd3c3095d 100644 (file)
--- a/mdadm.c
+++ b/mdadm.c
@@ -1,7 +1,7 @@
 /*
  * mdadm - manage Linux "md" devices aka RAID arrays.
  *
- * Copyright (C) 2001-2009 Neil Brown <neilb@suse.de>
+ * Copyright (C) 2001-2012 Neil Brown <neilb@suse.de>
  *
  *
  *    This program is free software; you can redistribute it and/or modify
 #include <ctype.h>
 
 
+static int scan_assemble(int autof, struct supertype *ss,
+                        int readonly, int runstop,
+                        struct mddev_ident *ident,
+                        char *homehost, int require_homehost,
+                        int verbose, int force,
+                        int freeze_reshape);
+
 int main(int argc, char *argv[])
 {
        int mode = 0;
@@ -73,6 +80,7 @@ int main(int argc, char *argv[])
        int test = 0;
        int export = 0;
        int assume_clean = 0;
+       char *prefer = NULL;
        char *symlinks = NULL;
        int grow_continue = 0;
        /* autof indicates whether and how to create device node.
@@ -176,7 +184,7 @@ int main(int argc, char *argv[])
 
                /*
                 * --offroot sets first char of argv[0] to @. This is used
-                * by systemd to signal that the tast was launched from
+                * by systemd to signal that the task was launched from
                 * initrd/initramfs and should be preserved during shutdown
                 */
                case OffRootOpt:
@@ -184,6 +192,13 @@ int main(int argc, char *argv[])
                        __offroot = 1;
                        continue;
 
+               case Prefer:
+                       if (prefer)
+                               free(prefer);
+                       if (asprintf(&prefer, "/%s/", optarg) <= 0)
+                               prefer = NULL;
+                       continue;
+
                case ':':
                case '?':
                        fputs(Usage, stderr);
@@ -212,15 +227,23 @@ int main(int argc, char *argv[])
                        }
                        break;
 
-               case 'A': newmode = ASSEMBLE; shortopt = short_bitmap_auto_options; break;
-               case 'B': newmode = BUILD; shortopt = short_bitmap_auto_options; break;
-               case 'C': newmode = CREATE; shortopt = short_bitmap_auto_options; break;
-               case 'F': newmode = MONITOR;break;
+               case 'A': newmode = ASSEMBLE;
+                       shortopt = short_bitmap_auto_options;
+                       break;
+               case 'B': newmode = BUILD;
+                       shortopt = short_bitmap_auto_options;
+                       break;
+               case 'C': newmode = CREATE;
+                       shortopt = short_bitmap_auto_options;
+                       break;
+               case 'F': newmode = MONITOR;
+                       break;
                case 'G': newmode = GROW;
                        shortopt = short_bitmap_options;
                        break;
                case 'I': newmode = INCREMENTAL;
-                       shortopt = short_bitmap_auto_options; break;
+                       shortopt = short_bitmap_auto_options;
+                       break;
                case AutoDetect:
                        newmode = AUTODETECT;
                        break;
@@ -244,7 +267,7 @@ int main(int argc, char *argv[])
                case KillSubarray:
                case UpdateSubarray:
                case UdevRules:
-               case 'K':
+               case KillOpt:
                        if (!mode)
                                newmode = MISC;
                        break;
@@ -578,7 +601,7 @@ int main(int argc, char *argv[])
                        ident.raid_disks = raiddisks;
                        continue;
 
-               case O(CREATE,'x'): /* number of spare (eXtra) discs */
+               case O(CREATE,'x'): /* number of spare (eXtra) disks */
                        if (sparedisks) {
                                fprintf(stderr,Name ": spare-devices set twice: %d and %s\n",
                                        sparedisks, optarg);
@@ -825,7 +848,7 @@ int main(int argc, char *argv[])
                case O(MONITOR,'r'): /* rebuild increments */
                case O(MONITOR,Increment):
                        increments = atoi(optarg);
-                       if (increments>99 || increments<1) {
+                       if (increments > 99 || increments < 1) {
                                fprintf(stderr, Name ": please specify positive integer between 1 and 99 as rebuild increments.\n");
                                exit(2);
                        }
@@ -872,6 +895,7 @@ int main(int argc, char *argv[])
                case O(MONITOR, NoSharing):
                        spare_sharing = 0;
                        continue;
+
                        /* now the general management options.  Some are applicable
                         * to other modes. None have arguments.
                         */
@@ -924,7 +948,7 @@ int main(int argc, char *argv[])
                case O(MISC,'Q'):
                case O(MISC,'D'):
                case O(MISC,'E'):
-               case O(MISC,'K'):
+               case O(MISC,KillOpt):
                case O(MISC,'R'):
                case O(MISC,'S'):
                case O(MISC,'X'):
@@ -1035,7 +1059,7 @@ int main(int argc, char *argv[])
                case O(CREATE,Bitmap): /* here we create the bitmap */
                        if (strcmp(optarg, "none") == 0) {
                                fprintf(stderr, Name ": '--bitmap none' only"
-                                       " support for --grow\n");
+                                       " supported for --grow\n");
                                exit(2);
                        }
                        /* FALL THROUGH */
@@ -1056,15 +1080,14 @@ int main(int argc, char *argv[])
                case O(BUILD,BitmapChunk):
                case O(CREATE,BitmapChunk): /* bitmap chunksize */
                        bitmap_chunk = parse_size(optarg);
-                       if (bitmap_chunk < 0 ||
+                       if (bitmap_chunk <= 0 ||
                            bitmap_chunk & (bitmap_chunk - 1)) {
                                fprintf(stderr,
                                        Name ": invalid bitmap chunksize: %s\n",
                                        optarg);
                                exit(2);
                        }
-                       /* convert sectors to B, chunk of 0 means 512B */
-                       bitmap_chunk = bitmap_chunk ? bitmap_chunk * 512 : 512;
+                       bitmap_chunk = bitmap_chunk * 512;
                        continue;
 
                case O(GROW, WriteBehind):
@@ -1151,12 +1174,13 @@ int main(int argc, char *argv[])
         *
         * That is mosty checked in the per-mode stuff but...
         *
-        * For @,B,C  and A without -s, the first device listed must be an md device
-        * we check that here and open it.
+        * For @,B,C and A without -s, the first device listed must be
+        * an md device.  We check that here and open it.
         */
 
-       if (mode==MANAGE || mode == BUILD || mode == CREATE || mode == GROW ||
-           (mode == ASSEMBLE && ! scan)) {
+       if (mode == MANAGE || mode == BUILD || mode == CREATE
+           || mode == GROW
+           || (mode == ASSEMBLE && ! scan)) {
                if (devs_found < 1) {
                        fprintf(stderr, Name ": an md device must be given in this mode\n");
                        exit(2);
@@ -1198,7 +1222,7 @@ int main(int argc, char *argv[])
        }
 
        if (raiddisks) {
-               if (raiddisks == 1 &&  !force && level != -5) {
+               if (raiddisks == 1 &&  !force && level != LEVEL_FAULTY) {
                        fprintf(stderr, Name ": '1' is an unusual number of drives for an array, so it is probably\n"
                                "     a mistake.  If you really mean it you will need to specify --force before\n"
                                "     setting the number of drives.\n");
@@ -1219,9 +1243,10 @@ int main(int argc, char *argv[])
                require_homehost = 0;
        }
 
-       if (!((mode == MISC && devmode == 'E')
-             || (mode == MONITOR && spare_sharing == 0)) &&
-           geteuid() != 0) {
+       if ((mode == MISC && devmode == 'E')
+           || (mode == MONITOR && spare_sharing == 0))
+               /* Anyone may try this */;
+       else if (geteuid() != 0) {
                fprintf(stderr, Name ": must be super-user to perform this action\n");
                exit(1);
        }
@@ -1271,7 +1296,7 @@ int main(int argc, char *argv[])
                                      homehost, require_homehost,
                                      verbose-quiet, force,
                                      freeze_reshape);
-               else if (devs_found>0) {
+               else if (devs_found > 0) {
                        if (update && devs_found > 1) {
                                fprintf(stderr, Name ": can only update a single array at a time\n");
                                exit(1);
@@ -1298,22 +1323,6 @@ int main(int argc, char *argv[])
                                               freeze_reshape);
                        }
                } else {
-                       struct mddev_ident *a, *array_list =  conf_get_ident(NULL);
-                       struct mddev_dev *devlist = conf_get_devs();
-                       struct map_ent *map = NULL;
-                       int cnt = 0;
-                       int failures, successes;
-
-                       if (conf_verify_devnames(array_list)) {
-                               fprintf(stderr, Name
-                                       ": Duplicate MD device names in "
-                                       "conf file were found.\n");
-                               exit(1);
-                       }
-                       if (devlist == NULL) {
-                               fprintf(stderr, Name ": No devices listed in conf file were found.\n");
-                               exit(1);
-                       }
                        if (update) {
                                fprintf(stderr, Name ": --update not meaningful with a --scan assembly.\n");
                                exit(1);
@@ -1322,83 +1331,13 @@ int main(int argc, char *argv[])
                                fprintf(stderr, Name ": --backup_file not meaningful with a --scan assembly.\n");
                                exit(1);
                        }
-                       for (a = array_list; a ; a = a->next) {
-                               a->assembled = 0;
-                               if (a->autof == 0)
-                                       a->autof = autof;
-                       }
-                       if (map_lock(&map))
-                               fprintf(stderr, Name " %s: failed to get "
-                                       "exclusive lock on mapfile\n",
-                                       __func__);
-                       do {
-                               failures = 0;
-                               successes = 0;
-                               rv = 0;
-                               for (a = array_list; a ; a = a->next) {
-                                       int r;
-                                       if (a->assembled)
-                                               continue;
-                                       if (a->devname &&
-                                           strcasecmp(a->devname, "<ignore>") == 0)
-                                               continue;
-                               
-                                       r = Assemble(ss, a->devname,
-                                                    a,
-                                                    NULL, NULL, 0,
-                                                    readonly, runstop, NULL,
-                                                    homehost, require_homehost,
-                                                    verbose-quiet, force,
-                                                    freeze_reshape);
-                                       if (r == 0) {
-                                               a->assembled = 1;
-                                               successes++;
-                                       } else
-                                               failures++;
-                                       rv |= r;
-                                       cnt++;
-                               }
-                       } while (failures && successes);
-                       if (homehost && cnt == 0) {
-                               /* Maybe we can auto-assemble something.
-                                * Repeatedly call Assemble in auto-assemble mode
-                                * until it fails
-                                */
-                               int rv2;
-                               int acnt;
-                               ident.autof = autof;
-                               do {
-                                       struct mddev_dev *devlist = conf_get_devs();
-                                       acnt = 0;
-                                       do {
-                                               rv2 = Assemble(ss, NULL,
-                                                              &ident,
-                                                              devlist, NULL, 0,
-                                                              readonly,
-                                                              runstop, NULL,
-                                                              homehost,
-                                                              require_homehost,
-                                                              verbose-quiet,
-                                                              force,
-                                                              freeze_reshape);
-                                               if (rv2==0) {
-                                                       cnt++;
-                                                       acnt++;
-                                               }
-                                       } while (rv2!=2);
-                                       /* Incase there are stacked devices, we need to go around again */
-                               } while (acnt);
-                               if (cnt == 0 && rv == 0) {
-                                       fprintf(stderr, Name ": No arrays found in config file or automatically\n");
-                                       rv = 1;
-                               } else if (cnt)
-                                       rv = 0;
-                       } else if (cnt == 0 && rv == 0) {
-                               fprintf(stderr, Name ": No arrays found in config file\n");
-                               rv = 1;
-                       }
-                       map_unlock(&map);
+                       rv = scan_assemble(autof, ss, readonly, runstop,
+                                          &ident, homehost,
+                                          require_homehost,
+                                          verbose - quiet,
+                                          force, freeze_reshape);
                }
+
                break;
        case BUILD:
                if (delay == 0) delay = DEFAULT_BITMAP_DELAY;
@@ -1499,7 +1438,7 @@ int main(int argc, char *argv[])
                                                if (devmode == 'D')
                                                        rv |= Detail(name, v,
                                                                     export, test,
-                                                                    homehost);
+                                                                    homehost, prefer);
                                                else
                                                        rv |= WaitClean(name, -1, v);
                                                put_md_name(name);
@@ -1553,9 +1492,9 @@ int main(int argc, char *argv[])
                                case 'D':
                                        rv |= Detail(dv->devname,
                                                     brief?1+verbose:0,
-                                                    export, test, homehost);
+                                                    export, test, homehost, prefer);
                                        continue;
-                               case 'K': /* Zero superblock */
+                               case KillOpt: /* Zero superblock */
                                        if (ss)
                                                rv |= Kill(dv->devname, ss, force, quiet,0);
                                        else {
@@ -1627,7 +1566,8 @@ int main(int argc, char *argv[])
                }
                rv= Monitor(devlist, mailaddr, program,
                            delay?delay:60, daemonise, scan, oneshot,
-                           dosyslog, test, pidfile, increments, spare_sharing);
+                           dosyslog, test, pidfile, increments,
+                           spare_sharing, prefer);
                break;
 
        case GROW:
@@ -1748,3 +1688,106 @@ int main(int argc, char *argv[])
        }
        exit(rv);
 }
+
+static int scan_assemble(int autof, struct supertype *ss,
+                        int readonly, int runstop,
+                        struct mddev_ident *ident,
+                        char *homehost, int require_homehost,
+                        int verbose, int force,
+                        int freeze_reshape)
+{
+       struct mddev_ident *a, *array_list =  conf_get_ident(NULL);
+       struct mddev_dev *devlist = conf_get_devs();
+       struct map_ent *map = NULL;
+       int cnt = 0;
+       int rv = 0;
+       int failures, successes;
+
+       if (conf_verify_devnames(array_list)) {
+               fprintf(stderr, Name
+                       ": Duplicate MD device names in "
+                       "conf file were found.\n");
+               return 1;
+       }
+       if (devlist == NULL) {
+               fprintf(stderr, Name ": No devices listed in conf file were found.\n");
+               return 1;
+       }
+       for (a = array_list; a ; a = a->next) {
+               a->assembled = 0;
+               if (a->autof == 0)
+                       a->autof = autof;
+       }
+       if (map_lock(&map))
+               fprintf(stderr, Name " %s: failed to get "
+                       "exclusive lock on mapfile\n",
+                       __func__);
+       do {
+               failures = 0;
+               successes = 0;
+               rv = 0;
+               for (a = array_list; a ; a = a->next) {
+                       int r;
+                       if (a->assembled)
+                               continue;
+                       if (a->devname &&
+                           strcasecmp(a->devname, "<ignore>") == 0)
+                               continue;
+                               
+                       r = Assemble(ss, a->devname,
+                                    a,
+                                    NULL, NULL, 0,
+                                    readonly, runstop, NULL,
+                                    homehost, require_homehost,
+                                    verbose, force,
+                                    freeze_reshape);
+                       if (r == 0) {
+                               a->assembled = 1;
+                               successes++;
+                       } else
+                               failures++;
+                       rv |= r;
+                       cnt++;
+               }
+       } while (failures && successes);
+       if (homehost && cnt == 0) {
+               /* Maybe we can auto-assemble something.
+                * Repeatedly call Assemble in auto-assemble mode
+                * until it fails
+                */
+               int rv2;
+               int acnt;
+               ident->autof = autof;
+               do {
+                       struct mddev_dev *devlist = conf_get_devs();
+                       acnt = 0;
+                       do {
+                               rv2 = Assemble(ss, NULL,
+                                              ident,
+                                              devlist, NULL, 0,
+                                              readonly,
+                                              runstop, NULL,
+                                              homehost,
+                                              require_homehost,
+                                              verbose,
+                                              force,
+                                              freeze_reshape);
+                               if (rv2==0) {
+                                       cnt++;
+                                       acnt++;
+                               }
+                       } while (rv2!=2);
+                       /* Incase there are stacked devices, we need to go around again */
+               } while (acnt);
+               if (cnt == 0 && rv == 0) {
+                       fprintf(stderr, Name ": No arrays found in config file or automatically\n");
+                       rv = 1;
+               } else if (cnt)
+                       rv = 0;
+       } else if (cnt == 0 && rv == 0) {
+               fprintf(stderr, Name ": No arrays found in config file\n");
+               rv = 1;
+       }
+       map_unlock(&map);
+       return rv;
+}