]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Assemble.c
teach imsm and ddf what st->subarray means at load_super time
[thirdparty/mdadm.git] / Assemble.c
index 4d12edc019f2a29f4d7a2f5b125a526c5c848595..3c3a004fc8045a67b16351a4bde7d7d3b67f8c04 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");
@@ -263,6 +260,13 @@ int Assemble(struct supertype *st, char *mddev,
                                fprintf(stderr, Name ": no recogniseable superblock on %s\n",
                                        devname);
                        tmpdev->used = 2;
+               } else if (auto_assem && st == NULL &&
+                          !conf_test_metadata(tst->ss->name)) {
+                       if (report_missmatch)
+                               fprintf(stderr, Name ": %s has metadata type %s for which "
+                                       "auto-assembly is disabled\n",
+                                       devname, tst->ss->name);
+                       tmpdev->used = 2;
                } else if (tst->ss->load_super(tst,dfd, NULL)) {
                        if (report_missmatch)
                                fprintf( stderr, Name ": no RAID superblock on %s\n",
@@ -473,16 +477,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;
-       switch (st->ss->match_home(st, homehost)) {
-       case 0:
-               trustworthy = FOREIGN;
-               name = content->name;
-               break;
+       name = content->name;
+       switch (st->ss->match_home(st, homehost)
+               ?: st->ss->match_home(st, "any")) {
        case 1:
                trustworthy = LOCAL;
                name = strchr(content->name, ':');
@@ -491,22 +493,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) {
@@ -1069,7 +1079,7 @@ int Assemble(struct supertype *st, char *mddev,
                                fprintf(stderr, "\n");
                        }
                        sysfs_uevent(content, "change");
-                       wait_for(chosen_name);
+                       wait_for(chosen_name, mdfd);
                        close(mdfd);
                        return 0;
                }
@@ -1104,8 +1114,8 @@ int Assemble(struct supertype *st, char *mddev,
                                                                      (4 * content->array.chunk_size / 4096) + 1);
                                        }
                                }
+                               wait_for(mddev, mdfd);
                                close(mdfd);
-                               wait_for(mddev);
                                if (auto_assem) {
                                        int usecs = 1;
                                        /* There is a nasty race with 'mdadm --monitor'.
@@ -1228,45 +1238,58 @@ int assemble_container_content(struct supertype *st, int mdfd,
                sysfs_free(sra);
 
        for (dev = content->devs; dev; dev = dev->next)
-               if (sysfs_add_disk(content, dev) == 0)
+               if (sysfs_add_disk(content, dev, 1) == 0)
                        working++;
                else if (errno == EEXIST)
                        preexist++;
        if (working == 0) {
                close(mdfd);
                return 1;/* Nothing new, don't try to start */
-       } else if (runstop > 0 ||
+       }
+       
+       map_update(&map, fd2devnum(mdfd),
+                  content->text_version,
+                  content->uuid, chosen_name);
+
+       if (runstop > 0 ||
                 (working + preexist) >= content->array.working_disks) {
+               int err;
 
-               map_update(&map, fd2devnum(mdfd),
-                          content->text_version,
-                          content->uuid, chosen_name);
                switch(content->array.level) {
                case LEVEL_LINEAR:
                case LEVEL_MULTIPATH:
                case 0:
-                       sysfs_set_str(content, NULL, "array_state",
-                                     "active");
+                       err = sysfs_set_str(content, NULL, "array_state",
+                                           "active");
                        break;
                default:
-                       sysfs_set_str(content, NULL, "array_state",
+                       err = sysfs_set_str(content, NULL, "array_state",
                                      "readonly");
                        /* start mdmon if needed. */
-                       if (!mdmon_running(st->container_dev))
-                               start_mdmon(st->container_dev);
-                       ping_monitor(devnum2devname(st->container_dev));
+                       if (!err) {
+                               if (!mdmon_running(st->container_dev))
+                                       start_mdmon(st->container_dev);
+                               ping_monitor(devnum2devname(st->container_dev));
+                       }
                        break;
                }
-               sysfs_set_safemode(content, content->safe_mode_delay);
+               if (!err)
+                       sysfs_set_safemode(content, content->safe_mode_delay);
                if (verbose >= 0) {
-                       fprintf(stderr, Name
-                               ": Started %s with %d devices",
-                               chosen_name, working + preexist);
+                       if (err)
+                               fprintf(stderr, Name
+                                       ": array %s now has %d devices",
+                                       chosen_name, working + preexist);
+                       else
+                               fprintf(stderr, Name
+                                       ": Started %s with %d devices",
+                                       chosen_name, working + preexist);
                        if (preexist)
                                fprintf(stderr, " (%d new)", working);
                        fprintf(stderr, "\n");
                }
-               wait_for(chosen_name);
+               if (!err)
+                       wait_for(chosen_name, mdfd);
                close(mdfd);
                return 0;
                /* FIXME should have an O_EXCL and wait for read-auto */