]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Assemble.c
RebuildMap: handle missing disks
[thirdparty/mdadm.git] / Assemble.c
index e421f22d2eddd0ddfd0e307b95fdb27a08e98e58..99f3599184cd4c4aad2ac69eb024197c5fcfa8fa 100644 (file)
@@ -138,7 +138,9 @@ int Assemble(struct supertype *st, char *mddev,
         */
        int mdfd;
        int clean;
-       int auto_assem = (mddev == NULL);
+       int auto_assem = (mddev == NULL && !ident->uuid_set &&
+                         ident->super_minor == UnSet && ident->name[0] == 0
+                         && ident->container == NULL && ident->member == NULL);
        int old_linux = 0;
        int vers = vers; /* Keep gcc quite - it really is initialised */
        struct {
@@ -166,7 +168,6 @@ int Assemble(struct supertype *st, char *mddev,
        mddev_dev_t tmpdev;
        struct mdinfo info;
        struct mdinfo *content = NULL;
-       mdu_array_info_t tmp_inf;
        char *avail;
        int nextspare = 0;
        char *name = NULL;
@@ -318,7 +319,7 @@ int Assemble(struct supertype *st, char *mddev,
 
                        tmpdev->content = content->next;
                        if (tmpdev->content == NULL)
-                               tmpdev->used = 1;
+                               tmpdev->used = 2;
 
                } else if (ident->container || ident->member) {
                        /* No chance of this matching if we don't have
@@ -394,12 +395,15 @@ int Assemble(struct supertype *st, char *mddev,
                         * looking.  If the chosen member is active, skip.
                         */
                        if (is_member_busy(content->text_version)) {
+                               if (report_missmatch)
+                                       fprintf(stderr, Name ": member %s in %s is already assembled\n",
+                                               content->text_version,
+                                               devname);
+                               tst->ss->free_super(tst);
+                               tst = NULL;
+                               content = NULL;
                                if (auto_assem)
                                        goto loop;
-                               fprintf(stderr, Name ": member %s in %s is already assembled\n",
-                                       content->text_version,
-                                       devname);
-                               tst->ss->free_super(tst);
                                return 1;
                        }
                        st = tst; tst = NULL;
@@ -520,7 +524,7 @@ int Assemble(struct supertype *st, char *mddev,
                close(mdfd);
                return 1;
        }
-       if (ioctl(mdfd, GET_ARRAY_INFO, &tmp_inf)==0) {
+       if (mddev_busy(fd2devnum(mdfd))) {
                fprintf(stderr, Name ": %s already active, cannot restart it!\n",
                        mddev);
                for (tmpdev = devlist ;
@@ -765,7 +769,6 @@ int Assemble(struct supertype *st, char *mddev,
                        int j = best[i];
                        if (j>=0 &&
                            !devices[j].uptodate &&
-                           devices[j].i.events > 0 &&
                            (chosen_drive < 0 ||
                             devices[j].i.events
                             > devices[chosen_drive].i.events))
@@ -823,7 +826,6 @@ int Assemble(struct supertype *st, char *mddev,
                        int j = best[i];
                        if (j >= 0 &&
                            !devices[j].uptodate &&
-                           devices[j].i.events > 0 &&
                            devices[j].i.events == current_events) {
                                chosen_drive = j;
                                goto add_another;
@@ -887,6 +889,8 @@ int Assemble(struct supertype *st, char *mddev,
                        continue;
 
                devices[j].i.disk.state = desired_state;
+               if (!(devices[j].i.array.state & 1))
+                       clean = 0;
 
                if (st->ss->update_super(st, &devices[j].i, "assemble", NULL,
                                         verbose, 0, NULL)) {
@@ -1065,6 +1069,7 @@ int Assemble(struct supertype *st, char *mddev,
                                fprintf(stderr, "\n");
                        }
                        sysfs_uevent(content, "change");
+                       wait_for(chosen_name);
                        close(mdfd);
                        return 0;
                }
@@ -1085,7 +1090,22 @@ int Assemble(struct supertype *st, char *mddev,
                                                fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s");
                                        fprintf(stderr, ".\n");
                                }
+                               if (content->reshape_active &&
+                                   content->array.level >= 4 &&
+                                   content->array.level <= 6) {
+                                       /* might need to increase the size
+                                        * of the stripe cache - default is 256
+                                        */
+                                       if (256 < 4 * (content->array.chunk_size/4096)) {
+                                               struct mdinfo *sra = sysfs_read(mdfd, 0, 0);
+                                               if (sra)
+                                                       sysfs_set_num(sra, NULL,
+                                                                     "stripe_cache_size",
+                                                                     (4 * content->array.chunk_size / 4096) + 1);
+                                       }
+                               }
                                close(mdfd);
+                               wait_for(mddev);
                                if (auto_assem) {
                                        int usecs = 1;
                                        /* There is a nasty race with 'mdadm --monitor'.
@@ -1167,6 +1187,7 @@ int Assemble(struct supertype *st, char *mddev,
                }
                if (auto_assem)
                        ioctl(mdfd, STOP_ARRAY, NULL);
+               close(mdfd);
                return 1;
        } else {
                /* The "chosen_drive" is a good choice, and if necessary, the superblock has
@@ -1199,8 +1220,10 @@ int assemble_container_content(struct supertype *st, int mdfd,
 
        sra = sysfs_read(mdfd, 0, GET_VERSION);
        if (sra == NULL || strcmp(sra->text_version, content->text_version) != 0)
-               if (sysfs_set_array(content, md_get_version(mdfd)) != 0)
+               if (sysfs_set_array(content, md_get_version(mdfd)) != 0) {
+                       close(mdfd);
                        return 1;
+               }
        if (sra)
                sysfs_free(sra);
 
@@ -1209,47 +1232,63 @@ int assemble_container_content(struct supertype *st, int mdfd,
                        working++;
                else if (errno == EEXIST)
                        preexist++;
-       if (working == 0)
-               /* Nothing new, don't try to start */ ;
-       else if (runstop > 0 ||
+       if (working == 0) {
+               close(mdfd);
+               return 1;/* Nothing new, don't try to start */
+       } else 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");
                }
+               if (!err)
+                       wait_for(chosen_name);
+               close(mdfd);
+               return 0;
                /* FIXME should have an O_EXCL and wait for read-auto */
-       } else
+       } else {
                if (verbose >= 0)
                        fprintf(stderr, Name
                                ": %s assembled with %d devices but "
                                "not started\n",
                                chosen_name, working);
-       map_update(&map, fd2devnum(mdfd),
-                  content->text_version,
-                  content->uuid, chosen_name);
-
-       return 0;
+               close(mdfd);
+               return 1;
+       }
 }
 #endif