]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - mdadm.c
Release 3.2.6 - stability release
[thirdparty/mdadm.git] / mdadm.c
diff --git a/mdadm.c b/mdadm.c
index 96d32b53059f0f5dac98ab8ae4e103ae977e3b75..846bc9641af062d7436721e72794cb66c3903521 100644 (file)
--- a/mdadm.c
+++ b/mdadm.c
@@ -73,7 +73,9 @@ 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.
         * bottom 3 bits are style.  Rest (when shifted) are number of parts
         * 0  - unset
@@ -112,6 +114,8 @@ int main(int argc, char *argv[])
 
        int mdfd = -1;
 
+       int freeze_reshape = 0;
+
        srandom(time(0) ^ getpid());
 
        ident.uuid_set=0;
@@ -171,6 +175,23 @@ int main(int argc, char *argv[])
                                homehost = optarg;
                        continue;
 
+               /*
+                * --offroot sets first char of argv[0] to @. This is used
+                * by systemd to signal that the tast was launched from
+                * initrd/initramfs and should be preserved during shutdown
+                */
+               case OffRootOpt:
+                       argv[0][0] = '@';
+                       __offroot = 1;
+                       continue;
+
+               case Prefer:
+                       if (prefer)
+                               free(prefer);
+                       if (asprintf(&prefer, "/%s/", optarg) <= 0)
+                               prefer = NULL;
+                       continue;
+
                case ':':
                case '?':
                        fputs(Usage, stderr);
@@ -209,13 +230,17 @@ int main(int argc, char *argv[])
                case 'I': newmode = INCREMENTAL;
                        shortopt = short_bitmap_auto_options; break;
                case AutoDetect:
-                       newmode = AUTODETECT; break;
+                       newmode = AUTODETECT;
+                       break;
 
                case MiscOpt:
                case 'D':
                case 'E':
                case 'X':
-               case 'Q': newmode = MISC; break;
+               case 'Q':
+                       newmode = MISC;
+                       break;
+
                case 'R':
                case 'S':
                case 'o':
@@ -226,17 +251,15 @@ int main(int argc, char *argv[])
                case DetailPlatform:
                case KillSubarray:
                case UpdateSubarray:
-                       if (opt == KillSubarray || opt == UpdateSubarray) {
-                               if (subarray) {
-                                       fprintf(stderr, Name ": subarray can only"
-                                               " be specified once\n");
-                                       exit(2);
-                               }
-                               subarray = optarg;
-                       }
                case UdevRules:
-               case 'K': if (!mode) newmode = MISC; break;
-               case NoSharing: newmode = MONITOR; break;
+               case 'K':
+                       if (!mode)
+                               newmode = MISC;
+                       break;
+
+               case NoSharing:
+                       newmode = MONITOR;
+                       break;
                }
                if (mode && newmode == mode) {
                        /* everybody happy ! */
@@ -253,6 +276,12 @@ int main(int argc, char *argv[])
                        exit(2);
                } else if (!mode && newmode) {
                        mode = newmode;
+                       if (mode == MISC && devs_found) {
+                               fprintf(stderr, Name ": No action given for %s in --misc mode\n",
+                                       devlist->devname);
+                               fprintf(stderr,"       Action options must come before device names\n");
+                               exit(2);
+                       }
                } else {
                        /* special case of -c --help */
                        if ((opt == 'c' || opt == ConfigFile) &&
@@ -355,12 +384,12 @@ int main(int argc, char *argv[])
                                exit(2);
                        }
                        chunk = parse_size(optarg);
-                       if (chunk < 8 || ((chunk-1)&chunk)) {
+                       if (chunk < 8 || (chunk&1)) {
                                fprintf(stderr, Name ": invalid chunk/rounding value: %s\n",
                                        optarg);
                                exit(2);
                        }
-                       /* Covert sectors to K */
+                       /* Convert sectors to K */
                        chunk /= 2;
                        continue;
 
@@ -536,6 +565,7 @@ int main(int argc, char *argv[])
 
                case O(CREATE,AssumeClean):
                case O(BUILD,AssumeClean): /* assume clean */
+               case O(GROW,AssumeClean):
                        assume_clean = 1;
                        continue;
 
@@ -602,10 +632,15 @@ int main(int argc, char *argv[])
                case O(ASSEMBLE,Force): /* force assembly */
                case O(MISC,'f'): /* force zero */
                case O(MISC,Force): /* force zero */
+               case O(MANAGE,Force): /* add device which is too large */
                        force=1;
                        continue;
-
                        /* now for the Assemble options */
+               case O(ASSEMBLE, FreezeReshape):   /* Freeze reshape during
+                                                   * initrd phase */
+               case O(INCREMENTAL, FreezeReshape):
+                       freeze_reshape = 1;
+                       continue;
                case O(CREATE,'u'): /* uuid of array */
                case O(ASSEMBLE,'u'): /* uuid of array */
                        if (ident.uuid_set) {
@@ -833,6 +868,7 @@ int main(int argc, char *argv[])
                        continue;
                case O(MONITOR,'1'): /* oneshot */
                        oneshot = 1;
+                       spare_sharing = 0;
                        continue;
                case O(MONITOR,'t'): /* test */
                        test = 1;
@@ -908,6 +944,14 @@ int main(int argc, char *argv[])
                case O(MISC, DetailPlatform):
                case O(MISC, KillSubarray):
                case O(MISC, UpdateSubarray):
+                       if (opt == KillSubarray || opt == UpdateSubarray) {
+                               if (subarray) {
+                                       fprintf(stderr, Name ": subarray can only"
+                                               " be specified once\n");
+                                       exit(2);
+                               }
+                               subarray = optarg;
+                       }
                        if (devmode && devmode != opt &&
                            (devmode == 'E' || (opt == 'E' && devmode != 'Q'))) {
                                fprintf(stderr, Name ": --examine/-E cannot be given with ");
@@ -981,6 +1025,11 @@ int main(int argc, char *argv[])
                        backup_file = optarg;
                        continue;
 
+               case O(GROW, Continue):
+                       /* Continue interrupted grow
+                        */
+                       grow_continue = 1;
+                       continue;
                case O(ASSEMBLE, InvalidBackup):
                        /* Acknowledge that the backupfile is invalid, but ask
                         * to continue anyway
@@ -1015,15 +1064,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):
@@ -1178,7 +1226,8 @@ int main(int argc, char *argv[])
                require_homehost = 0;
        }
 
-       if ((mode != MISC || devmode != 'E') &&
+       if (!((mode == MISC && devmode == 'E')
+             || (mode == MONITOR && spare_sharing == 0)) &&
            geteuid() != 0) {
                fprintf(stderr, Name ": must be super-user to perform this action\n");
                exit(1);
@@ -1195,7 +1244,7 @@ int main(int argc, char *argv[])
                if (!rv && devs_found>1)
                        rv = Manage_subdevs(devlist->devname, mdfd,
                                            devlist->next, verbose-quiet, test,
-                                           update);
+                                           update, force);
                if (!rv && readonly < 0)
                        rv = Manage_ro(devlist->devname, mdfd, readonly);
                if (!rv && runstop)
@@ -1219,14 +1268,16 @@ int main(int argc, char *argv[])
                                               NULL, backup_file, invalid_backup,
                                               readonly, runstop, update,
                                               homehost, require_homehost,
-                                              verbose-quiet, force);
+                                              verbose-quiet, force,
+                                              freeze_reshape);
                        }
                } else if (!scan)
                        rv = Assemble(ss, devlist->devname, &ident,
                                      devlist->next, backup_file, invalid_backup,
                                      readonly, runstop, update,
                                      homehost, require_homehost,
-                                     verbose-quiet, force);
+                                     verbose-quiet, force,
+                                     freeze_reshape);
                else if (devs_found>0) {
                        if (update && devs_found > 1) {
                                fprintf(stderr, Name ": can only update a single array at a time\n");
@@ -1250,13 +1301,22 @@ int main(int argc, char *argv[])
                                               NULL, backup_file, invalid_backup,
                                               readonly, runstop, update,
                                               homehost, require_homehost,
-                                              verbose-quiet, force);
+                                              verbose-quiet, force,
+                                              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);
@@ -1274,6 +1334,10 @@ int main(int argc, char *argv[])
                                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;
@@ -1291,7 +1355,8 @@ int main(int argc, char *argv[])
                                                     NULL, NULL, 0,
                                                     readonly, runstop, NULL,
                                                     homehost, require_homehost,
-                                                    verbose-quiet, force);
+                                                    verbose-quiet, force,
+                                                    freeze_reshape);
                                        if (r == 0) {
                                                a->assembled = 1;
                                                successes++;
@@ -1316,9 +1381,13 @@ int main(int argc, char *argv[])
                                                rv2 = Assemble(ss, NULL,
                                                               &ident,
                                                               devlist, NULL, 0,
-                                                              readonly, runstop, NULL,
-                                                              homehost, require_homehost,
-                                                              verbose-quiet, force);
+                                                              readonly,
+                                                              runstop, NULL,
+                                                              homehost,
+                                                              require_homehost,
+                                                              verbose-quiet,
+                                                              force,
+                                                              freeze_reshape);
                                                if (rv2==0) {
                                                        cnt++;
                                                        acnt++;
@@ -1335,6 +1404,7 @@ int main(int argc, char *argv[])
                                fprintf(stderr, Name ": No arrays found in config file\n");
                                rv = 1;
                        }
+                       map_unlock(&map);
                }
                break;
        case BUILD:
@@ -1436,7 +1506,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);
@@ -1490,7 +1560,7 @@ 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 */
                                        if (ss)
@@ -1564,7 +1634,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:
@@ -1626,12 +1697,16 @@ int main(int argc, char *argv[])
                                delay = DEFAULT_BITMAP_DELAY;
                        rv = Grow_addbitmap(devlist->devname, mdfd, bitmap_file,
                                            bitmap_chunk, delay, write_behind, force);
-               } else if (size >= 0 || raiddisks != 0 || layout_str != NULL
+               } else if (grow_continue)
+                       rv = Grow_continue_command(devlist->devname,
+                                                  mdfd, backup_file,
+                                                  verbose);
+               else if (size >= 0 || raiddisks != 0 || layout_str != NULL
                           || chunk != 0 || level != UnSet) {
                        rv = Grow_reshape(devlist->devname, mdfd, quiet, backup_file,
                                          size, level, layout_str, chunk, raiddisks,
                                          devlist->next,
-                                         force);
+                                         assume_clean, force);
                } else if (array_size < 0)
                        fprintf(stderr, Name ": no changes to --grow\n");
                break;
@@ -1672,7 +1747,8 @@ int main(int argc, char *argv[])
                else
                        rv = Incremental(devlist->devname, verbose-quiet,
                                         runstop, ss, homehost,
-                                        require_homehost, autof);
+                                        require_homehost, autof,
+                                        freeze_reshape);
                break;
        case AUTODETECT:
                autodetect();