]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Assemble.c
--update: add 'bbl' and 'no-bbl' to the list of known updates.
[thirdparty/mdadm.git] / Assemble.c
index af02633cde3a5f63da9f847057c5f3d3644175cb..cdcdb0f8658bf8b0350bc627fd50eb1a64c423ee 100644 (file)
@@ -366,9 +366,6 @@ static int select_devices(struct mddev_dev *devlist,
                        tmpdev = NULL;
                        goto loop;
                } else {
-                       int rv = 0;
-                       struct mddev_ident *match;
-
                        content = *contentp;
                        tst->ss->getinfo_super(tst, content, NULL);
 
@@ -377,25 +374,33 @@ static int select_devices(struct mddev_dev *devlist,
                                           report_mismatch ? devname : NULL))
                                goto loop;
 
-                       match = conf_match(tst, content, devname,
-                                          report_mismatch ? c->verbose : -1,
-                                          &rv);
-                       if (!match && rv == 2)
-                               goto loop;
-                       if (match && match->devname &&
-                           strcasecmp(match->devname, "<ignore>") == 0) {
-                               if (report_mismatch)
-                                       pr_err("%s is a member of an explicitly ignored array\n",
-                                              devname);
-                               goto loop;
-                       }
-                       if (match && !ident_matches(match, content, tst,
-                                                   c->homehost, c->update,
-                                                   report_mismatch ? devname : NULL))
-                               /* Array exists  in mdadm.conf but some
-                                * details don't match, so reject it
+                       if (auto_assem) {
+                               /* Never auto-assemble things that conflict
+                                * with mdadm.conf in some way
                                 */
-                               goto loop;
+                               struct mddev_ident *match;
+                               int rv = 0;
+
+                               match = conf_match(tst, content, devname,
+                                                  report_mismatch ? c->verbose : -1,
+                                                  &rv);
+                               if (!match && rv == 2)
+                                       goto loop;
+                               if (match && match->devname &&
+                                   strcasecmp(match->devname, "<ignore>") == 0) {
+                                       if (report_mismatch)
+                                               pr_err("%s is a member of an explicitly ignored array\n",
+                                                      devname);
+                                       goto loop;
+                               }
+                               if (match && !ident_matches(match, content, tst,
+                                                           c->homehost, c->update,
+                                                           report_mismatch ? devname : NULL))
+                                       /* Array exists  in mdadm.conf but some
+                                        * details don't match, so reject it
+                                        */
+                                       goto loop;
+                       }
 
                        /* should be safe to try an exclusive open now, we
                         * have rejected anything that some other mdadm might
@@ -572,6 +577,7 @@ static int load_devices(struct devs *devices, char *devmap,
        for (tmpdev = devlist; tmpdev; tmpdev=tmpdev->next) {
                char *devname = tmpdev->devname;
                struct stat stb;
+               struct supertype *tst;
                int i;
 
                if (tmpdev->used != 1)
@@ -582,7 +588,6 @@ static int load_devices(struct devs *devices, char *devmap,
                        int dfd;
                        /* prepare useful information in info structures */
                        struct stat stb2;
-                       struct supertype *tst;
                        int err;
                        fstat(mdfd, &stb2);
 
@@ -611,6 +616,8 @@ static int load_devices(struct devs *devices, char *devmap,
                                close(mdfd);
                                free(devices);
                                free(devmap);
+                               tst->ss->free_super(tst);
+                               free(tst);
                                *stp = st;
                                return -1;
                        }
@@ -660,15 +667,13 @@ static int load_devices(struct devs *devices, char *devmap,
                                else
                                        bitmap_done = 1;
                        }
-                       tst->ss->free_super(tst);
                } else
 #endif
                {
-                       struct supertype *tst = dup_super(st);
-                       int dfd;
-                       dfd = dev_open(devname,
-                                      tmpdev->disposition == 'I'
-                                      ? O_RDWR : (O_RDWR|O_EXCL));
+                       int dfd = dev_open(devname,
+                                          tmpdev->disposition == 'I'
+                                          ? O_RDWR : (O_RDWR|O_EXCL));
+                       tst = dup_super(st);
 
                        if (dfd < 0 || tst->ss->load_super(tst, dfd, NULL) != 0) {
                                pr_err("cannot re-read metadata from %s - aborting\n",
@@ -678,11 +683,12 @@ static int load_devices(struct devs *devices, char *devmap,
                                close(mdfd);
                                free(devices);
                                free(devmap);
+                               tst->ss->free_super(tst);
+                               free(tst);
                                *stp = st;
                                return -1;
                        }
                        tst->ss->getinfo_super(tst, content, devmap + devcnt * content->array.raid_disks);
-                       tst->ss->free_super(tst);
                        close(dfd);
                }
 
@@ -702,9 +708,15 @@ static int load_devices(struct devs *devices, char *devmap,
                if (devices[devcnt].i.disk.state == 6) {
                        if (most_recent < 0 ||
                            devices[devcnt].i.events
-                           > devices[most_recent].i.events)
+                           > devices[most_recent].i.events) {
+                               struct supertype *tmp = tst;
+                               tst = st;
+                               st = tmp;
                                most_recent = devcnt;
+                       }
                }
+               tst->ss->free_super(tst);
+               free(tst);
 
                if (content->array.level == LEVEL_MULTIPATH)
                        /* with multipath, the raid_disk from the superblock is meaningless */
@@ -994,6 +1006,22 @@ static int start_array(int mdfd,
                                        content->array.raid_disks);
                        fprintf(stderr, "\n");
                }
+
+               if (st->ss->validate_container) {
+                       struct mdinfo *devices_list;
+                       struct mdinfo *info_devices = xmalloc(sizeof(struct mdinfo)*(okcnt+sparecnt));
+                       unsigned int count;
+                       devices_list = NULL;
+                       for (count = 0; count < okcnt+sparecnt; count++) {
+                               info_devices[count] = devices[count].i;
+                               info_devices[count].next = devices_list;
+                               devices_list = &info_devices[count];
+                       }
+                       if (st->ss->validate_container(devices_list))
+                               pr_err("Mismatch detected!\n");
+                       free(info_devices);
+               }
+
                st->ss->free_super(st);
                sysfs_uevent(content, "change");
                if (err_ok && okcnt < (unsigned)content->array.raid_disks)
@@ -1037,7 +1065,7 @@ static int start_array(int mdfd,
                                           "array_state", "readonly");
                        if (rv == 0)
                                rv = Grow_continue(mdfd, st, content,
-                                                  c->backup_file,
+                                                  c->backup_file, 0,
                                                   c->freeze_reshape);
                } else if (c->readonly &&
                           sysfs_attribute_available(
@@ -1673,6 +1701,8 @@ try_again:
                        pr_err(":%s has an active reshape - checking "
                               "if critical section needs to be restored\n",
                               chosen_name);
+               if (!c->backup_file)
+                       c->backup_file = locate_backup(content->sys_name);
                enable_fds(bestcnt/2);
                for (i = 0; i < bestcnt/2; i++) {
                        int j = best[i*2];
@@ -1784,7 +1814,7 @@ int assemble_container_content(struct supertype *st, int mdfd,
                               struct mdinfo *content, struct context *c,
                               char *chosen_name, int *result)
 {
-       struct mdinfo *dev, *sra;
+       struct mdinfo *dev, *sra, *dev2;
        int working = 0, preexist = 0;
        int expansion = 0;
        struct map_ent *map = NULL;
@@ -1795,7 +1825,7 @@ int assemble_container_content(struct supertype *st, int mdfd,
 
        sysfs_init(content, mdfd, NULL);
 
-       sra = sysfs_read(mdfd, NULL, GET_VERSION);
+       sra = sysfs_read(mdfd, NULL, GET_VERSION|GET_DEVS);
        if (sra == NULL || strcmp(sra->text_version, content->text_version) != 0) {
                if (content->array.major_version == -1 &&
                    content->array.minor_version == -2 &&
@@ -1822,8 +1852,22 @@ int assemble_container_content(struct supertype *st, int mdfd,
        if (st->ss->external && content->recovery_blocked && start_reshape)
                block_subarray(content);
 
-       if (sra)
-               sysfs_free(sra);
+       for (dev2 = sra->devs; dev2; dev2 = dev2->next) {
+               for (dev = content->devs; dev; dev = dev->next)
+                       if (dev2->disk.major == dev->disk.major &&
+                           dev2->disk.minor == dev->disk.minor)
+                               break;
+               if (dev)
+                       continue;
+               /* Don't want this one any more */
+               if (sysfs_set_str(sra, dev2, "slot", "none") < 0 &&
+                   errno == EBUSY) {
+                       pr_err("Cannot remove old device %s: not updating %s\n", dev2->sys_name, sra->sys_name);
+                       sysfs_free(sra);
+                       return 1;
+               }
+               sysfs_set_str(sra, dev2, "state", "remove");
+       }
        old_raid_disks = content->array.raid_disks - content->delta_disks;
        avail = xcalloc(content->array.raid_disks, 1);
        for (dev = content->devs; dev; dev = dev->next) {
@@ -1838,6 +1882,7 @@ int assemble_container_content(struct supertype *st, int mdfd,
                } else if (errno == EEXIST)
                        preexist++;
        }
+       sysfs_free(sra);
        if (working + expansion == 0 && c->runstop <= 0) {
                free(avail);
                return 1;/* Nothing new, don't try to start */
@@ -1885,7 +1930,7 @@ int assemble_container_content(struct supertype *st, int mdfd,
                int spare = content->array.raid_disks + expansion;
                if (restore_backup(st, content,
                                   working,
-                                  spare, c->backup_file, c->verbose) == 1)
+                                  spare, &c->backup_file, c->verbose) == 1)
                        return 1;
 
                err = sysfs_set_str(content, NULL,
@@ -1903,7 +1948,7 @@ int assemble_container_content(struct supertype *st, int mdfd,
                }
 
                err = Grow_continue(mdfd, st, content, c->backup_file,
-                                   c->freeze_reshape);
+                                   0, c->freeze_reshape);
        } else switch(content->array.level) {
                case LEVEL_LINEAR:
                case LEVEL_MULTIPATH: