]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Assemble.c
tests: add test that DDF marks missing devices as failed on assembly.
[thirdparty/mdadm.git] / Assemble.c
index 7e8e7957035239eae63f20debcf2b615186e0d9c..05ace561fb507bb6a557b3d15e6d35f18517400b 100644 (file)
@@ -551,7 +551,7 @@ struct devs {
 };
 
 static int load_devices(struct devs *devices, char *devmap,
-                       struct mddev_ident *ident, struct supertype *st,
+                       struct mddev_ident *ident, struct supertype **stp,
                        struct mddev_dev *devlist, struct context *c,
                        struct mdinfo *content,
                        int mdfd, char *mddev,
@@ -567,10 +567,12 @@ static int load_devices(struct devs *devices, char *devmap,
        int most_recent = -1;
        int bestcnt = 0;
        int *best = *bestp;
+       struct supertype *st = *stp;
 
        for (tmpdev = devlist; tmpdev; tmpdev=tmpdev->next) {
                char *devname = tmpdev->devname;
                struct stat stb;
+               struct supertype *tst;
                int i;
 
                if (tmpdev->used != 1)
@@ -581,7 +583,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);
 
@@ -610,6 +611,9 @@ 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);
@@ -636,6 +640,7 @@ static int load_devices(struct devs *devices, char *devmap,
                                close(dfd);
                                free(devices);
                                free(devmap);
+                               *stp = st;
                                return -1;
                        }
                        if (strcmp(c->update, "uuid")==0 &&
@@ -657,15 +662,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",
@@ -675,10 +678,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);
                }
 
@@ -698,9 +703,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 */
@@ -759,6 +770,7 @@ static int load_devices(struct devs *devices, char *devmap,
                                close(mdfd);
                                free(devices);
                                free(devmap);
+                               *stp = st;
                                return -1;
                        }
                        if (best[i] == -1
@@ -772,6 +784,7 @@ static int load_devices(struct devs *devices, char *devmap,
                *most_recentp = most_recent;
        *bestcntp = bestcnt;
        *bestp = best;
+       *stp = st;
        return devcnt;
 }
 
@@ -990,6 +1003,10 @@ static int start_array(int mdfd,
                }
                st->ss->free_super(st);
                sysfs_uevent(content, "change");
+               if (err_ok && okcnt < (unsigned)content->array.raid_disks)
+                       /* Was partial, is still partial, so signal an error
+                        * to ensure we don't retry */
+                       return 1;
                return 0;
        }
 
@@ -1428,7 +1445,7 @@ try_again:
        /* Ok, no bad inconsistancy, we can try updating etc */
        devices = xcalloc(num_devs, sizeof(*devices));
        devmap = xcalloc(num_devs, content->array.raid_disks);
-       devcnt = load_devices(devices, devmap, ident, st, devlist,
+       devcnt = load_devices(devices, devmap, ident, &st, devlist,
                              c, content, mdfd, mddev,
                              &most_recent, &bestcnt, &best, inargv);
        if (devcnt < 0)