X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fmdadm.git;a=blobdiff_plain;f=Assemble.c;h=65a679b650e1e7af29487c279f53161f51adbd7d;hp=16dec24678e03abe057dafe6079d9a3d9d4ceee8;hb=f35f25259279573c6274e2783536c0b0a399bdd4;hpb=a19c88b83db3cc25affb75fe2d5531c964379d96 diff --git a/Assemble.c b/Assemble.c index 16dec246..65a679b6 100644 --- a/Assemble.c +++ b/Assemble.c @@ -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; @@ -367,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) { @@ -377,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); @@ -481,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); @@ -541,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. @@ -568,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; @@ -654,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); @@ -734,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; iss->external) { - char ver[100]; - strcat(strcpy(ver, "external:"), st->ss->text_version); - sra = sysfs_read(mdfd, 0, 0); - if ((vers % 100) < 2 || - sra == NULL || - sysfs_set_str(sra, NULL, "metadata_version", - ver) < 0) { - fprintf(stderr, Name ": This kernel does not " - "support external metadata.\n"); - return 1; - } - rv = sysfs_set_array(sra, &info); - } else -#endif - 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; @@ -911,21 +893,8 @@ int Assemble(struct supertype *st, char *mddev, int mdfd, j = chosen_drive; if (j >= 0 /* && devices[j].uptodate */) { -#ifndef MDASSEMBLE - if (st->ss->external) { - int fd = dev_open(devices[j].devname, - O_RDONLY); - if (fd < 0) - rv = 1; - else { - rv = sysfs_add_disk(sra, fd, - &devices[j].i); - close(fd); - } - } else -#endif - rv = ioctl(mdfd, ADD_NEW_DISK, - &devices[j].i.disk); + rv = add_disk(mdfd, st, &info, &devices[j].i); + if (rv) { fprintf(stderr, Name ": failed to add " "%s to %s: %s\n", @@ -948,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, @@ -970,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. * @@ -1007,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) { @@ -1041,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