]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Assemble.c
config: add 'homehost' option to 'AUTO' line.
[thirdparty/mdadm.git] / Assemble.c
index 4966a79822045b19331497952f9f1ad37259e9dc..b3052ac37f65d4ba863992254a382ed84801a6d2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * mdadm - manage Linux "md" devices aka RAID arrays.
  *
- * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
+ * Copyright (C) 2001-2009 Neil Brown <neilb@suse.de>
  *
  *
  *    This program is free software; you can redistribute it and/or modify
  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  *    Author: Neil Brown
- *    Email: <neilb@cse.unsw.edu.au>
- *    Paper: Neil Brown
- *           School of Computer Science and Engineering
- *           The University of New South Wales
- *           Sydney, 2052
- *           Australia
+ *    Email: <neilb@suse.de>
  */
 
 #include       "mdadm.h"
@@ -79,7 +74,7 @@ int Assemble(struct supertype *st, char *mddev,
             mddev_ident_t ident,
             mddev_dev_t devlist, char *backup_file,
             int readonly, int runstop,
-            char *update, char *homehost,
+            char *update, char *homehost, int require_homehost,
             int verbose, int force)
 {
        /*
@@ -140,7 +135,7 @@ int Assemble(struct supertype *st, char *mddev,
        int clean;
        int auto_assem = (mddev == NULL && !ident->uuid_set &&
                          ident->super_minor == UnSet && ident->name[0] == 0
-                         && ident->container == NULL && ident->member == NULL);
+                         && (ident->container == NULL || ident->member == NULL));
        int old_linux = 0;
        int vers = vers; /* Keep gcc quite - it really is initialised */
        struct {
@@ -188,6 +183,8 @@ int Assemble(struct supertype *st, char *mddev,
        if (!devlist &&
            ident->uuid_set == 0 &&
            ident->super_minor < 0 &&
+           ident->name[0] == 0 &&
+           (ident->container == NULL || ident->member == NULL) &&
            ident->devices == NULL) {
                fprintf(stderr, Name ": No identity information available for %s - cannot assemble.\n",
                        mddev ? mddev : "further assembly");
@@ -264,7 +261,8 @@ int Assemble(struct supertype *st, char *mddev,
                                        devname);
                        tmpdev->used = 2;
                } else if (auto_assem && st == NULL &&
-                          !conf_test_metadata(tst->ss->name)) {
+                          !conf_test_metadata(tst->ss->name,
+                                              tst->ss->match_home(tst, homehost) == 1)) {
                        if (report_missmatch)
                                fprintf(stderr, Name ": %s has metadata type %s for which "
                                        "auto-assembly is disabled\n",
@@ -318,11 +316,16 @@ int Assemble(struct supertype *st, char *mddev,
                        }
                        /* It is worth looking inside this container.
                         */
+                       if (verbose > 0)
+                               fprintf(stderr, Name ": looking in container %s\n",
+                                       devname);
                next_member:
                        if (tmpdev->content)
                                content = tmpdev->content;
                        else
                                content = tst->ss->container_content(tst);
+                       if (!content)
+                               goto loop; /* empty container */
 
                        tmpdev->content = content->next;
                        if (tmpdev->content == NULL)
@@ -406,6 +409,9 @@ int Assemble(struct supertype *st, char *mddev,
                                        fprintf(stderr, Name ": member %s in %s is already assembled\n",
                                                content->text_version,
                                                devname);
+                       skip:
+                               if (tmpdev->content)
+                                       goto next_member;
                                tst->ss->free_super(tst);
                                tst = NULL;
                                content = NULL;
@@ -413,14 +419,32 @@ int Assemble(struct supertype *st, char *mddev,
                                        goto loop;
                                return 1;
                        }
+                       if (ident->member && ident->member[0]) {
+                               char *s = strchr(content->text_version+1, '/');
+                               if (s == NULL) {
+                                       fprintf(stderr, Name ": badly formatted version: %s\n",
+                                               content->text_version);
+                                       goto skip;
+                               }
+                               if (strcmp(ident->member, s+1) != 0) {
+                                       if (report_missmatch)
+                                               fprintf(stderr,
+                                                       Name ": skipping wrong member %s\n",
+                                                       content->text_version);
+                                       goto skip;
+                               }
+                       }
                        st = tst; tst = NULL;
-                       if (!auto_assem && tmpdev->next != NULL) {
+                       if (!auto_assem && inargv && tmpdev->next != NULL) {
                                fprintf(stderr, Name ": %s is a container, but is not "
                                        "only device given: confused and aborting\n",
                                        devname);
                                st->ss->free_super(st);
                                return 1;
                        }
+                       if (verbose > 0)
+                               fprintf(stderr, Name ": found match on member %s in %s\n",
+                                       content->text_version, devname);
                        break;
                }
                if (st == NULL)
@@ -480,17 +504,14 @@ int Assemble(struct supertype *st, char *mddev,
        if (!st || !st->sb || !content)
                return 2;
 
-       /* Now need to open array the device.  Use create_mddev */
+       /* Now need to open the array device.  Use create_mddev */
        if (content == &info)
                st->ss->getinfo_super(st, content);
 
        trustworthy = FOREIGN;
+       name = content->name;
        switch (st->ss->match_home(st, homehost)
                ?: st->ss->match_home(st, "any")) {
-       case 0:
-               trustworthy = FOREIGN;
-               name = content->name;
-               break;
        case 1:
                trustworthy = LOCAL;
                name = strchr(content->name, ':');
@@ -499,22 +520,30 @@ int Assemble(struct supertype *st, char *mddev,
                else
                        name = content->name;
                break;
-       case -1:
-               trustworthy = FOREIGN;
-               break;
        }
-       if (!auto_assem && trustworthy == FOREIGN)
-               /* If the array is listed in mdadm or on
+       if (!auto_assem)
+               /* If the array is listed in mdadm.conf or on
                 * command line, then we trust the name
                 * even if the array doesn't look local
                 */
                trustworthy = LOCAL;
 
-       if (content->name[0] == 0 &&
+       if (name[0] == 0 &&
            content->array.level == LEVEL_CONTAINER) {
                name = content->text_version;
                trustworthy = METADATA;
        }
+
+       if (name[0] && trustworthy != LOCAL &&
+           ! require_homehost &&
+           conf_name_is_free(name))
+               trustworthy = LOCAL;
+
+       if (trustworthy == LOCAL &&
+           strchr(name, ':'))
+               /* Ignore 'host:' prefix of name */
+               name = strchr(name, ':')+1;
+
        mdfd = create_mddev(mddev, name, ident->autof, trustworthy,
                            chosen_name);
        if (mdfd < 0) {
@@ -561,6 +590,7 @@ int Assemble(struct supertype *st, char *mddev,
 #endif
        /* Ok, no bad inconsistancy, we can try updating etc */
        bitmap_done = 0;
+       content->update_private = NULL;
        for (tmpdev = devlist; tmpdev; tmpdev=tmpdev->next) if (tmpdev->used == 1) {
                char *devname = tmpdev->devname;
                struct stat stb;
@@ -590,7 +620,14 @@ int Assemble(struct supertype *st, char *mddev,
                        remove_partitions(dfd);
 
                        tst = dup_super(st);
-                       tst->ss->load_super(tst, dfd, NULL);
+                       if (dfd < 0 || tst->ss->load_super(tst, dfd, NULL) != 0) {
+                               fprintf(stderr, Name ": cannot re-read metadata from %s - aborting\n",
+                                       devname);
+                               if (dfd >= 0)
+                                       close(dfd);
+                               close(mdfd);
+                               return 1;
+                       }
                        tst->ss->getinfo_super(tst, content);
 
                        memcpy(content->uuid, ident->uuid, 16);
@@ -633,7 +670,14 @@ int Assemble(struct supertype *st, char *mddev,
 
                        remove_partitions(dfd);
 
-                       tst->ss->load_super(tst, dfd, NULL);
+                       if (dfd < 0 || tst->ss->load_super(tst, dfd, NULL) != 0) {
+                               fprintf(stderr, Name ": cannot re-read metadata from %s - aborting\n",
+                                       devname);
+                               if (dfd >= 0)
+                                       close(dfd);
+                               close(mdfd);
+                               return 1;
+                       }
                        tst->ss->getinfo_super(tst, content);
                        tst->ss->free_super(tst);
                        close(dfd);
@@ -654,7 +698,7 @@ int Assemble(struct supertype *st, char *mddev,
                            > devices[most_recent].i.events)
                                most_recent = devcnt;
                }
-               if (content->array.level == -4)
+               if (content->array.level == LEVEL_MULTIPATH)
                        /* with multipath, the raid_disk from the superblock is meaningless */
                        i = devcnt;
                else
@@ -713,6 +757,8 @@ int Assemble(struct supertype *st, char *mddev,
                }
                devcnt++;
        }
+       free(content->update_private);
+       content->update_private = NULL;
 
        if (devcnt == 0) {
                fprintf(stderr, Name ": no devices found for %s\n",
@@ -745,8 +791,8 @@ int Assemble(struct supertype *st, char *mddev,
                /* note: we ignore error flags in multipath arrays
                 * as they don't make sense
                 */
-               if (content->array.level != -4)
-                       if (!(devices[j].i.disk.state & (1<<MD_DISK_SYNC))) {
+               if (content->array.level != LEVEL_MULTIPATH)
+                       if (!(devices[j].i.disk.state & (1<<MD_DISK_ACTIVE))) {
                                if (!(devices[j].i.disk.state
                                      & (1<<MD_DISK_FAULTY)))
                                        sparecnt++;
@@ -755,7 +801,8 @@ int Assemble(struct supertype *st, char *mddev,
                if (devices[j].i.events+event_margin >=
                    devices[most_recent].i.events) {
                        devices[j].uptodate = 1;
-                       if (i < content->array.raid_disks) {
+                       if (i < content->array.raid_disks &&
+                           devices[j].i.recovery_start == MaxSector) {
                                okcnt++;
                                avail[i]=1;
                        } else
@@ -777,6 +824,7 @@ int Assemble(struct supertype *st, char *mddev,
                        int j = best[i];
                        if (j>=0 &&
                            !devices[j].uptodate &&
+                           devices[j].i.recovery_start == MaxSector &&
                            (chosen_drive < 0 ||
                             devices[j].i.events
                             > devices[chosen_drive].i.events))
@@ -959,6 +1007,10 @@ int Assemble(struct supertype *st, char *mddev,
        if (content->reshape_active) {
                int err = 0;
                int *fdlist = malloc(sizeof(int)* bestcnt);
+               if (verbose > 0)
+                       fprintf(stderr, Name ":%s has an active reshape - checking "
+                               "if critical section needs to be restored\n",
+                               chosen_name);
                for (i=0; i<bestcnt; i++) {
                        int j = best[i];
                        if (j >= 0) {
@@ -973,13 +1025,15 @@ int Assemble(struct supertype *st, char *mddev,
                                fdlist[i] = -1;
                }
                if (!err)
-                       err = Grow_restart(st, content, fdlist, bestcnt, backup_file);
+                       err = Grow_restart(st, content, fdlist, bestcnt, backup_file, verbose > 0);
                while (i>0) {
                        i--;
                        if (fdlist[i]>=0) close(fdlist[i]);
                }
                if (err) {
                        fprintf(stderr, Name ": Failed to restore critical section for reshape, sorry.\n");
+                       if (backup_file == NULL)
+                               fprintf(stderr,"      Possibly you needed to specify the --backup-file\n");
                        close(mdfd);
                        return err;
                }
@@ -1004,12 +1058,14 @@ int Assemble(struct supertype *st, char *mddev,
                if (rv) {
                        fprintf(stderr, Name ": failed to set array info for %s: %s\n",
                                mddev, strerror(errno));
+                       ioctl(mdfd, STOP_ARRAY, NULL);
                        close(mdfd);
                        return 1;
                }
                if (ident->bitmap_fd >= 0) {
                        if (ioctl(mdfd, SET_BITMAP_FILE, ident->bitmap_fd) != 0) {
                                fprintf(stderr, Name ": SET_BITMAP_FILE failed.\n");
+                               ioctl(mdfd, STOP_ARRAY, NULL);
                                close(mdfd);
                                return 1;
                        }
@@ -1019,12 +1075,14 @@ int Assemble(struct supertype *st, char *mddev,
                        if (bmfd < 0) {
                                fprintf(stderr, Name ": Could not open bitmap file %s\n",
                                        ident->bitmap_file);
+                               ioctl(mdfd, STOP_ARRAY, NULL);
                                close(mdfd);
                                return 1;
                        }
                        if (ioctl(mdfd, SET_BITMAP_FILE, bmfd) != 0) {
                                fprintf(stderr, Name ": Failed to set bitmapfile for %s\n", mddev);
                                close(bmfd);
+                               ioctl(mdfd, STOP_ARRAY, NULL);
                                close(mdfd);
                                return 1;
                        }
@@ -1088,7 +1146,20 @@ int Assemble(struct supertype *st, char *mddev,
                              content->array.layout, clean, avail, okcnt) &&
                       (okcnt >= req_cnt || start_partial_ok)
                             ))) {
-                       if (ioctl(mdfd, RUN_ARRAY, NULL)==0) {
+                       /* This array is good-to-go.
+                        * If a reshape is in progress then we might need to
+                        * continue monitoring it.  In that case we start
+                        * it read-only and let the grow code make it writable.
+                        */
+                       int rv;
+#ifndef MDASSEMBLE
+                       if (content->reshape_active &&
+                           content->delta_disks <= 0)
+                               rv = Grow_continue(mdfd, st, content, backup_file);
+                       else
+#endif
+                               rv = ioctl(mdfd, RUN_ARRAY, NULL);
+                       if (rv == 0) {
                                if (verbose >= 0) {
                                        fprintf(stderr, Name ": %s has been started with %d drive%s",
                                                mddev, okcnt, okcnt==1?"":"s");