X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fmdadm.git;a=blobdiff_plain;f=Assemble.c;h=cc906db51bcfb09e296e7f98e829e1fca28bf69a;hp=e762c693e502321a7c1e87d495a07f521714f11b;hb=881990a2e440d58d2c1d070e9005225f56d21260;hpb=4b1ac34b51a3783ab528b1af307156fab057b543 diff --git a/Assemble.c b/Assemble.c index e762c693..cc906db5 100644 --- a/Assemble.c +++ b/Assemble.c @@ -29,7 +29,7 @@ #include "mdadm.h" -int Assemble(char *mddev, int mdfd, +int Assemble(struct supertype *st, char *mddev, int mdfd, mddev_ident_t ident, char *conffile, mddev_dev_t devlist, int readonly, int runstop, @@ -101,6 +101,7 @@ int Assemble(char *mddev, int mdfd, int uptodate; int state; int raid_disk; + int disk_nr; } *devices; int *best = NULL; /* indexed by raid_disk */ unsigned int bestcnt = 0; @@ -116,6 +117,9 @@ int Assemble(char *mddev, int mdfd, unsigned int num_devs; mddev_dev_t tmpdev; struct mdinfo info; + struct mddev_ident_s ident2; + char *avail; + int nextspare = 0; vers = md_get_version(mdfd); if (vers <= 0) { @@ -164,8 +168,9 @@ int Assemble(char *mddev, int mdfd, } devices = malloc(num_devs * sizeof(*devices)); + if (!st && ident->st) st = ident->st; - if (verbose) + if (verbose>0) fprintf(stderr, Name ": looking for devices for %s\n", mddev); @@ -173,13 +178,14 @@ int Assemble(char *mddev, int mdfd, char *devname; int dfd; struct stat stb; + struct supertype *tst = st; devname = devlist->devname; devlist = devlist->next; if (ident->devices && !match_oneof(ident->devices, devname)) { - if (inargv || verbose) + if ((inargv && verbose>=0) || verbose > 0) fprintf(stderr, Name ": %s is not one of %s\n", devname, ident->devices); continue; } @@ -189,54 +195,61 @@ int Assemble(char *mddev, int mdfd, super = NULL; } - dfd = open(devname, O_RDONLY|O_EXCL, 0); + dfd = dev_open(devname, O_RDONLY|O_EXCL); if (dfd < 0) { - if (inargv || verbose) + if ((inargv && verbose >= 0) || verbose > 0) fprintf(stderr, Name ": cannot open device %s: %s\n", devname, strerror(errno)); } else if (fstat(dfd, &stb)< 0) { /* Impossible! */ fprintf(stderr, Name ": fstat failed for %s: %s\n", devname, strerror(errno)); - close(dfd); } else if ((stb.st_mode & S_IFMT) != S_IFBLK) { fprintf(stderr, Name ": %s is not a block device.\n", devname); - close(dfd); - } else if (load_super0(dfd, &super, NULL)) { - if (inargv || verbose) + } else if (!tst && (tst = guess_super(dfd)) == NULL) { + if ((inargv && verbose >= 0) || verbose > 0) + fprintf(stderr, Name ": no recogniseable superblock\n"); + } else if (tst->ss->load_super(tst,dfd, &super, NULL)) { + if ((inargv && verbose >= 0) || verbose > 0) fprintf( stderr, Name ": no RAID superblock on %s\n", devname); - close(dfd); } else { - getinfo_super0(&info, super); - close(dfd); + tst->ss->getinfo_super(&info, &ident2, super); } + if (dfd >= 0) close(dfd); - if (ident->uuid_set && - (!super || same_uuid(info.uuid, ident->uuid)==0)) { - if (inargv || verbose) + if (ident->uuid_set && (!update || strcmp(update, "uuid")!= 0) && + (!super || same_uuid(info.uuid, ident->uuid, tst->ss->swapuuid)==0)) { + if ((inargv && verbose >= 0) || verbose > 0) fprintf(stderr, Name ": %s has wrong uuid.\n", devname); continue; } + if (ident->name[0] && + (!super || strncmp(ident2.name, ident->name, 32)!=0)) { + if ((inargv && verbose >= 0) || verbose > 0) + fprintf(stderr, Name ": %s has wrong name.\n", + devname); + continue; + } if (ident->super_minor != UnSet && (!super || ident->super_minor != info.array.md_minor)) { - if (inargv || verbose) + if ((inargv && verbose >= 0) || verbose > 0) fprintf(stderr, Name ": %s has wrong super-minor.\n", devname); continue; } if (ident->level != UnSet && (!super|| ident->level != info.array.level)) { - if (inargv || verbose) + if ((inargv && verbose >= 0) || verbose > 0) fprintf(stderr, Name ": %s has wrong raid level.\n", devname); continue; } if (ident->raid_disks != UnSet && (!super || ident->raid_disks!= info.array.raid_disks)) { - if (inargv || verbose) + if ((inargv && verbose >= 0) || verbose > 0) fprintf(stderr, Name ": %s requires wrong number of drives.\n", devname); continue; @@ -253,7 +266,10 @@ int Assemble(char *mddev, int mdfd, free(first_super); return 1; } - if (compare_super0(&first_super, super)) { + + + st = tst; /* commit to this format, if haven't already */ + if (st->ss->compare_super(&first_super, super)) { fprintf(stderr, Name ": superblock on %s doesn't match others - assembly aborted\n", devname); free(super); @@ -267,21 +283,35 @@ int Assemble(char *mddev, int mdfd, struct stat stb2; fstat(mdfd, &stb2); info.array.md_minor = minor(stb2.st_rdev); + + if (strcmp(update, "uuid")==0 && + !ident->uuid_set) { + int rfd; + if ((rfd = open("/dev/urandom", O_RDONLY)) < 0 || + read(rfd, ident->uuid, 16) != 16) { + *(__u32*)(ident->uuid) = random(); + *(__u32*)(ident->uuid+1) = random(); + *(__u32*)(ident->uuid+2) = random(); + *(__u32*)(ident->uuid+3) = random(); + } + if (rfd >= 0) close(rfd); + ident->uuid_set = 1; + } + memcpy(info.uuid, ident->uuid, 16); + st->ss->update_super(&info, super, update, devname, verbose); - update_super0(&info, super, update, devname, verbose); - - dfd = open(devname, O_RDWR|O_EXCL, 0); + dfd = dev_open(devname, O_RDWR|O_EXCL); if (dfd < 0) fprintf(stderr, Name ": Cannot open %s for superblock update\n", devname); - else if (store_super0(dfd, super)) + else if (st->ss->store_super(st, dfd, super)) fprintf(stderr, Name ": Could not re-write superblock on %s.\n", devname); if (dfd >= 0) close(dfd); } - if (verbose) + if (verbose > 0) fprintf(stderr, Name ": %s is identified as a member of %s, slot %d.\n", devname, mddev, info.disk.raid_disk); devices[devcnt].devname = devname; @@ -291,6 +321,7 @@ int Assemble(char *mddev, int mdfd, devices[devcnt].oldminor = info.disk.minor; devices[devcnt].events = info.events; devices[devcnt].raid_disk = info.disk.raid_disk; + devices[devcnt].disk_nr = info.disk.number; devices[devcnt].uptodate = 0; devices[devcnt].state = info.disk.state; if (most_recent < devcnt) { @@ -303,6 +334,11 @@ int Assemble(char *mddev, int mdfd, i = devcnt; else i = devices[devcnt].raid_disk; + if (i+1 == 0) { + if (nextspare < info.array.raid_disks) + nextspare = info.array.raid_disks; + i = nextspare++; + } if (i < 10000) { if (i >= bestcnt) { unsigned int newbestcnt = i+10; @@ -328,6 +364,9 @@ int Assemble(char *mddev, int mdfd, free(super); super = NULL; + if (update && strcmp(update, "byteorder")==0) + st->minor_version = 90; + if (devcnt == 0) { fprintf(stderr, Name ": no devices found for %s\n", mddev); @@ -335,16 +374,20 @@ int Assemble(char *mddev, int mdfd, return 1; } - getinfo_super0(&info, first_super); + st->ss->getinfo_super(&info, &ident2, first_super); /* now we have some devices that might be suitable. * I wonder how many */ + avail = malloc(info.array.raid_disks); + memset(avail, 0, info.array.raid_disks); okcnt = 0; sparecnt=0; for (i=0; i< bestcnt ;i++) { int j = best[i]; - int event_margin = !force; + int event_margin = 1; /* always allow a difference of '1' + * like the kernel does + */ if (j < 0) continue; /* note: we ignore error flags in multipath arrays * as they don't make sense @@ -358,13 +401,16 @@ int Assemble(char *mddev, int mdfd, if (devices[j].events+event_margin >= devices[most_recent].events) { devices[j].uptodate = 1; - if (i < info.array.raid_disks) + if (i < info.array.raid_disks) { okcnt++; - else + avail[i]=1; + } else sparecnt++; } } - while (force && !enough(info.array.level, info.array.raid_disks, okcnt)) { + while (force && !enough(info.array.level, info.array.raid_disks, + info.array.layout, + avail, okcnt)) { /* Choose the newest best drive which is * not up-to-date, update the superblock * and add it. @@ -382,18 +428,19 @@ int Assemble(char *mddev, int mdfd, } if (chosen_drive < 0) break; - fprintf(stderr, Name ": forcing event count in %s(%d) from %d upto %d\n", - devices[chosen_drive].devname, devices[chosen_drive].raid_disk, - (int)(devices[chosen_drive].events), - (int)(devices[most_recent].events)); - fd = open(devices[chosen_drive].devname, O_RDWR|O_EXCL); + if (verbose >= 0) + fprintf(stderr, Name ": forcing event count in %s(%d) from %d upto %d\n", + devices[chosen_drive].devname, devices[chosen_drive].raid_disk, + (int)(devices[chosen_drive].events), + (int)(devices[most_recent].events)); + fd = dev_open(devices[chosen_drive].devname, O_RDWR|O_EXCL); if (fd < 0) { fprintf(stderr, Name ": Couldn't open %s for write - not updating\n", devices[chosen_drive].devname); devices[chosen_drive].events = 0; continue; } - if (load_super0(fd, &super, NULL)) { + if (st->ss->load_super(st,fd, &super, NULL)) { close(fd); fprintf(stderr, Name ": RAID superblock disappeared from %s - not updating.\n", devices[chosen_drive].devname); @@ -401,9 +448,9 @@ int Assemble(char *mddev, int mdfd, continue; } info.events = devices[most_recent].events; - update_super0(&info, super, "force", devices[chosen_drive].devname, verbose); + st->ss->update_super(&info, super, "force", devices[chosen_drive].devname, verbose); - if (store_super0(fd, super)) { + if (st->ss->store_super(st, fd, super)) { close(fd); fprintf(stderr, Name ": Could not re-write superblock on %s\n", devices[chosen_drive].devname); @@ -414,6 +461,7 @@ int Assemble(char *mddev, int mdfd, close(fd); devices[chosen_drive].events = devices[most_recent].events; devices[chosen_drive].uptodate = 1; + avail[chosen_drive] = 1; okcnt++; free(super); } @@ -435,12 +483,12 @@ int Assemble(char *mddev, int mdfd, if (!devices[j].uptodate) continue; chosen_drive = j; - if ((fd=open(devices[j].devname, O_RDONLY|O_EXCL))< 0) { + if ((fd=dev_open(devices[j].devname, O_RDONLY|O_EXCL))< 0) { fprintf(stderr, Name ": Cannot open %s: %s\n", devices[j].devname, strerror(errno)); return 1; } - if (load_super0(fd, &super, NULL)) { + if (st->ss->load_super(st,fd, &super, NULL)) { close(fd); fprintf(stderr, Name ": RAID superblock has disappeared from %s\n", devices[j].devname); @@ -452,7 +500,7 @@ int Assemble(char *mddev, int mdfd, fprintf(stderr, Name ": No suitable drives found for %s\n", mddev); return 1; } - getinfo_super0(&info, super); + st->ss->getinfo_super(&info, &ident2, super); for (i=0; iss->update_super(&info, super, "assemble", NULL, verbose)) { if (force) { - fprintf(stderr, Name ": " - "clearing FAULTY flag for device %d in %s for %s\n", - j, mddev, devices[j].devname); + if (verbose >= 0) + fprintf(stderr, Name ": " + "clearing FAULTY flag for device %d in %s for %s\n", + j, mddev, devices[j].devname); change = 1; } else { - fprintf(stderr, Name ": " - "device %d in %s has wrong state in superblock, but %s seems ok\n", - i, mddev, devices[j].devname); + if (verbose >= -1) + fprintf(stderr, Name ": " + "device %d in %s has wrong state in superblock, but %s seems ok\n", + i, mddev, devices[j].devname); } } #if 0 @@ -492,19 +543,19 @@ int Assemble(char *mddev, int mdfd, } if (force && okcnt == info.array.raid_disks-1) { /* FIXME check event count */ - change += update_super0(&info, super, "force", - devices[chosen_drive].devname, 0); + change += st->ss->update_super(&info, super, "force", + devices[chosen_drive].devname, verbose); } if (change) { int fd; - fd = open(devices[chosen_drive].devname, O_RDWR|O_EXCL); + fd = dev_open(devices[chosen_drive].devname, O_RDWR|O_EXCL); if (fd < 0) { fprintf(stderr, Name ": Could open %s for write - cannot Assemble array.\n", devices[chosen_drive].devname); return 1; } - if (store_super0(fd, super)) { + if (st->ss->store_super(st, fd, super)) { close(fd); fprintf(stderr, Name ": Could not re-write superblock on %s\n", devices[chosen_drive].devname); @@ -520,11 +571,28 @@ int Assemble(char *mddev, int mdfd, /* Almost ready to actually *do* something */ if (!old_linux) { - if (ioctl(mdfd, SET_ARRAY_INFO, NULL) != 0) { + 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); + + if (rv) { fprintf(stderr, Name ": SET_ARRAY_INFO failed for %s: %s\n", mddev, strerror(errno)); return 1; } + if (ident->bitmap_fd >= 0) { + if (ioctl(mdfd, SET_BITMAP_FILE, ident->bitmap_fd) != 0) { + fprintf(stderr, Name ": SET_BITMAP_FILE failed.\n"); + return 1; + } + } + /* First, add the raid disks, but add the chosen one last */ for (i=0; i<= bestcnt; i++) { int j; @@ -549,27 +617,29 @@ int Assemble(char *mddev, int mdfd, okcnt--; else sparecnt--; - } else if (verbose) + } else if (verbose > 0) fprintf(stderr, Name ": added %s to %s as %d\n", devices[j].devname, mddev, devices[j].raid_disk); - } else if (verbose && i < info.array.raid_disks) + } else if (verbose > 0 && i < info.array.raid_disks) fprintf(stderr, Name ": no uptodate device for slot %d of %s\n", i, mddev); } if (runstop == 1 || (runstop == 0 && - ( enough(info.array.level, info.array.raid_disks, okcnt) && + ( enough(info.array.level, info.array.raid_disks, info.array.layout, avail, okcnt) && (okcnt >= req_cnt || start_partial_ok) ))) { if (ioctl(mdfd, RUN_ARRAY, NULL)==0) { - fprintf(stderr, Name ": %s has been started with %d drive%s", - mddev, okcnt, okcnt==1?"":"s"); - if (okcnt < info.array.raid_disks) - fprintf(stderr, " (out of %d)", info.array.raid_disks); - if (sparecnt) - fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s"); - fprintf(stderr, ".\n"); + if (verbose >= 0) { + fprintf(stderr, Name ": %s has been started with %d drive%s", + mddev, okcnt, okcnt==1?"":"s"); + if (okcnt < info.array.raid_disks) + fprintf(stderr, " (out of %d)", info.array.raid_disks); + if (sparecnt) + fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s"); + fprintf(stderr, ".\n"); + } return 0; } fprintf(stderr, Name ": failed to RUN_ARRAY %s: %s\n", @@ -581,17 +651,19 @@ int Assemble(char *mddev, int mdfd, mddev, okcnt, okcnt==1?"":"s"); return 0; } - fprintf(stderr, Name ": %s assembled from %d drive%s", mddev, okcnt, okcnt==1?"":"s"); - if (sparecnt) - fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s"); - if (!enough(info.array.level, info.array.raid_disks, okcnt)) - fprintf(stderr, " - not enough to start the array.\n"); - else { - if (req_cnt == info.array.raid_disks) - fprintf(stderr, " - need all %d to start it", req_cnt); - else - fprintf(stderr, " - need %d of %d to start", req_cnt, info.array.raid_disks); - fprintf(stderr, " (use --run to insist).\n"); + if (verbose >= 0) { + fprintf(stderr, Name ": %s assembled from %d drive%s", mddev, okcnt, okcnt==1?"":"s"); + if (sparecnt) + fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s"); + if (!enough(info.array.level, info.array.raid_disks, info.array.layout, avail, okcnt)) + fprintf(stderr, " - not enough to start the array.\n"); + else { + if (req_cnt == info.array.raid_disks) + fprintf(stderr, " - need all %d to start it", req_cnt); + else + fprintf(stderr, " - need %d of %d to start", req_cnt, info.array.raid_disks); + fprintf(stderr, " (use --run to insist).\n"); + } } return 1; } else {