]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Assemble.c
Move calls to SET_ARRAY_INFO to common helper.
[thirdparty/mdadm.git] / Assemble.c
index c7cc385da98d6b1e9a26d8531e08a4cd573eb8c7..65a679b650e1e7af29487c279f53161f51adbd7d 100644 (file)
@@ -140,6 +140,8 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
        char *avail;
        int nextspare = 0;
 
+       memset(&info, 0, sizeof(info));
+
        if (get_linux_version() < 2004000)
                old_linux = 1;
 
@@ -315,7 +317,8 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
                if (!tst || !tst->sb) {
                        fprintf(stderr, Name ": %s has no superblock - assembly aborted\n",
                                devname);
-                       st->ss->free_super(st);
+                       if (st)
+                               st->ss->free_super(st);
                        return 1;
                }
 
@@ -366,7 +369,8 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
                tmpdev->used = 1;
 
        loop:
-               tst->ss->free_super(tst);
+               if (tst)
+                       tst->ss->free_super(tst);
        }
 
        if (mdfd < 0) {
@@ -376,7 +380,7 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
                 */
                mdu_array_info_t inf;
                char *c;
-               if (!st->sb) {
+               if (!st || !st->sb) {
                        return 2;
                }
                st->ss->getinfo_super(st, &info);
@@ -480,7 +484,7 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
                } else
 #endif
                {
-                       struct supertype *tst = dup_super(st);;
+                       struct supertype *tst = dup_super(st);
                        int dfd;
                        dfd = dev_open(devname, O_RDWR|O_EXCL);
 
@@ -540,8 +544,8 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
                            == devices[devcnt].i.events
                            && (devices[best[i]].i.disk.minor
                                != devices[devcnt].i.disk.minor)
-                           && st->ss->major == 0
-                           && info.array.level != -4) {
+                           && st->ss == &super0
+                           && info.array.level != LEVEL_MULTIPATH) {
                                /* two different devices with identical superblock.
                                 * Could be a mis-detection caused by overlapping
                                 * partitions.  fail-safe.
@@ -567,17 +571,18 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
                devcnt++;
        }
 
-       if (update && strcmp(update, "byteorder")==0)
-               st->minor_version = 90;
-
        if (devcnt == 0) {
                fprintf(stderr, Name ": no devices found for %s\n",
                        mddev);
-               st->ss->free_super(st);
+               if (st)
+                       st->ss->free_super(st);
                if (must_close) close(mdfd);
                return 1;
        }
 
+       if (update && strcmp(update, "byteorder")==0)
+               st->minor_version = 90;
+
        st->ss->getinfo_super(st, &info);
        clean = info.array.state & 1;
 
@@ -653,7 +658,7 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
                        continue;
                }
                tst = dup_super(st);
-               if (tst->ss->load_super(st,fd, NULL)) {
+               if (tst->ss->load_super(tst,fd, NULL)) {
                        close(fd);
                        fprintf(stderr, Name ": RAID superblock disappeared from %s - not updating.\n",
                                devices[chosen_drive].devname);
@@ -733,6 +738,9 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
                return 1;
        }
        st->ss->getinfo_super(st, &info);
+#ifndef MDASSEMBLE
+       sysfs_init(&info, mdfd, 0);
+#endif
        for (i=0; i<bestcnt; i++) {
                int j = best[i];
                unsigned int desired_state;
@@ -842,17 +850,10 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
        /* Almost ready to actually *do* something */
        if (!old_linux) {
                int rv;
-               if ((vers % 100) >= 1) { /* can use different versions */
-                       mdu_array_info_t inf;
-                       memset(&inf, 0, sizeof(inf));
-                       inf.major_version = st->ss->major;
-                       inf.minor_version = st->minor_version;
-                       rv = ioctl(mdfd, SET_ARRAY_INFO, &inf);
-               } else
-                       rv = ioctl(mdfd, SET_ARRAY_INFO, NULL);
 
+               rv = set_array_info(mdfd, st, &info);
                if (rv) {
-                       fprintf(stderr, Name ": SET_ARRAY_INFO failed for %s: %s\n",
+                       fprintf(stderr, Name ": failed to set array info for %s: %s\n",
                                mddev, strerror(errno));
                        if (must_close) close(mdfd);
                        return 1;
@@ -892,8 +893,9 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
                                j = chosen_drive;
 
                        if (j >= 0 /* && devices[j].uptodate */) {
-                               if (ioctl(mdfd, ADD_NEW_DISK,
-                                         &devices[j].i.disk)!=0) {
+                               rv = add_disk(mdfd, st, &info, &devices[j].i);
+
+                               if (rv) {
                                        fprintf(stderr, Name ": failed to add "
                                                        "%s to %s: %s\n",
                                                devices[j].devname,
@@ -915,6 +917,21 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
                                        i, mddev);
                }
 
+               if (info.array.level == LEVEL_CONTAINER) {
+                       if (verbose >= 0) {
+                               fprintf(stderr, Name ": Container %s has been "
+                                       "assembled with %d drive%s",
+                                       mddev, okcnt, okcnt==1?"":"s");
+                               if (okcnt < info.array.raid_disks)
+                                       fprintf(stderr, " (out of %d)",
+                                               info.array.raid_disks);
+                               fprintf(stderr, "\n");
+                       }
+                       if (must_close)
+                               close(mdfd);
+                       return 0;
+               }
+
                if (runstop == 1 ||
                    (runstop <= 0 &&
                     ( enough(info.array.level, info.array.raid_disks,
@@ -937,7 +954,8 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
                                        /* There is a nasty race with 'mdadm --monitor'.
                                         * If it opens this device before we close it,
                                         * it gets an incomplete open on which IO
-                                        * doesn't work and the capacity if wrong.
+                                        * doesn't work and the capacity is
+                                        * wrong.
                                         * If we reopen (to check for layered devices)
                                         * before --monitor closes, we loose.
                                         *
@@ -974,7 +992,10 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
                                        "start the array while not clean "
                                        "- consider --force.\n");
 
-                       if (must_close) close(mdfd);
+                       if (must_close) {
+                               ioctl(mdfd, STOP_ARRAY, NULL);
+                               close(mdfd);
+                       }
                        return 1;
                }
                if (runstop == -1) {
@@ -1008,7 +1029,10 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
                                fprintf(stderr, " (use --run to insist).\n");
                        }
                }
-               if (must_close) close(mdfd);
+               if (must_close) {
+                       ioctl(mdfd, STOP_ARRAY, NULL);
+                       close(mdfd);
+               }
                return 1;
        } else {
                /* The "chosen_drive" is a good choice, and if necessary, the superblock has