Initial implementation of auto-assembly

This basically works, but needs various improvements and some tests.

Signed-off-by: Neil Brown <neilb@suse.de>
This commit is contained in:
Neil Brown 2006-05-26 00:50:15 +00:00
parent 8a46fe8487
commit da6b5ca9bd
3 changed files with 118 additions and 36 deletions

View File

@ -180,10 +180,14 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
} }
if (devlist == NULL) if (devlist == NULL)
devlist = conf_get_devs(conffile); devlist = conf_get_devs(conffile);
else inargv = 1; else if (mdfd >= 0)
inargv = 1;
tmpdev = devlist; num_devs = 0; tmpdev = devlist; num_devs = 0;
while (tmpdev) { while (tmpdev) {
if (tmpdev->used)
tmpdev->used = 2;
else
num_devs++; num_devs++;
tmpdev = tmpdev->next; tmpdev = tmpdev->next;
} }
@ -207,6 +211,8 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
struct stat stb; struct stat stb;
struct supertype *tst = st; struct supertype *tst = st;
if (tmpdev->used > 1) continue;
if (ident->devices && if (ident->devices &&
!match_oneof(ident->devices, devname)) { !match_oneof(ident->devices, devname)) {
if ((inargv && verbose>=0) || verbose > 0) if ((inargv && verbose>=0) || verbose > 0)
@ -224,16 +230,21 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
if ((inargv && verbose >= 0) || verbose > 0) if ((inargv && verbose >= 0) || verbose > 0)
fprintf(stderr, Name ": cannot open device %s: %s\n", fprintf(stderr, Name ": cannot open device %s: %s\n",
devname, strerror(errno)); devname, strerror(errno));
tmpdev->used = 2;
} else if (fstat(dfd, &stb)< 0) { } else if (fstat(dfd, &stb)< 0) {
/* Impossible! */ /* Impossible! */
fprintf(stderr, Name ": fstat failed for %s: %s\n", fprintf(stderr, Name ": fstat failed for %s: %s\n",
devname, strerror(errno)); devname, strerror(errno));
tmpdev->used = 2;
} else if ((stb.st_mode & S_IFMT) != S_IFBLK) { } else if ((stb.st_mode & S_IFMT) != S_IFBLK) {
fprintf(stderr, Name ": %s is not a block device.\n", fprintf(stderr, Name ": %s is not a block device.\n",
devname); devname);
tmpdev->used = 2;
} else if (!tst && (tst = guess_super(dfd)) == NULL) { } else if (!tst && (tst = guess_super(dfd)) == NULL) {
if ((inargv && verbose >= 0) || verbose > 0) if ((inargv && verbose >= 0) || verbose > 0)
fprintf(stderr, Name ": no recogniseable superblock\n"); fprintf(stderr, Name ": no recogniseable superblock on %s\n",
devname);
tmpdev->used = 2;
} else if (tst->ss->load_super(tst,dfd, &super, NULL)) { } else if (tst->ss->load_super(tst,dfd, &super, NULL)) {
if ((inargv && verbose >= 0) || verbose > 0) if ((inargv && verbose >= 0) || verbose > 0)
fprintf( stderr, Name ": no RAID superblock on %s\n", fprintf( stderr, Name ": no RAID superblock on %s\n",
@ -278,7 +289,17 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
devname); devname);
continue; continue;
} }
if (mdfd < 0) {
if (tst == NULL || super == NULL)
continue;
if (tst->ss->match_home(super, homehost)==0) {
if ((inargv && verbose >= 0) || verbose > 0)
fprintf(stderr, Name ": %s is not built for host %s.\n",
devname, homehost);
/* Auto-assemble, and this is not a usable host */
continue;
}
}
/* If we are this far, then we are nearly commited to this device. /* If we are this far, then we are nearly commited to this device.
* If the super_block doesn't exist, or doesn't match others, * If the super_block doesn't exist, or doesn't match others,
* then we probably cannot continue * then we probably cannot continue
@ -299,8 +320,12 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
st->minor_version != tst->minor_version || st->minor_version != tst->minor_version ||
st->ss->compare_super(&first_super, super) != 0) { st->ss->compare_super(&first_super, super) != 0) {
/* Some mismatch. If exactly one array matches this host, /* Some mismatch. If exactly one array matches this host,
* we can resolve on that one * we can resolve on that one.
* Or, if we are auto assembling, we just ignore the second
* for now.
*/ */
if (mdfd < 0)
continue;
if (homehost) { if (homehost) {
int first = st->ss->match_home(first_super, homehost); int first = st->ss->match_home(first_super, homehost);
int last = tst->ss->match_home(super, homehost); int last = tst->ss->match_home(super, homehost);
@ -339,14 +364,29 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
* We create a name '/dev/md/XXX' based on the info in the * We create a name '/dev/md/XXX' based on the info in the
* superblock, and call open_mddev on that * superblock, and call open_mddev on that
*/ */
asprintf(&mddev, "/dev/md/%s", info.name); mdu_array_info_t inf;
mdfd = open_mddev(mddev, 0); char *c;
if (!first_super) {
return 1;
}
st->ss->getinfo_super(&info, first_super);
c = strchr(info.name, ':');
if (c) c++; else c= info.name;
asprintf(&mddev, "/dev/md/%s", c);
mdfd = open_mddev(mddev, ident->autof);
if (mdfd < 0) if (mdfd < 0)
return mdfd; return mdfd;
vers = md_get_version(mdfd);
if (ioctl(mdfd, GET_ARRAY_INFO, &inf)==0) {
fprintf(stderr, Name ": %s already active, cannot restart it!\n", mddev);
close(mdfd);
free(first_super);
return 1;
}
} }
/* Ok, no bad inconsistancy, we can try updating etc */ /* Ok, no bad inconsistancy, we can try updating etc */
for (tmpdev = devlist; tmpdev; tmpdev=tmpdev->next) if (tmpdev->used) { for (tmpdev = devlist; tmpdev; tmpdev=tmpdev->next) if (tmpdev->used == 1) {
char *devname = tmpdev->devname; char *devname = tmpdev->devname;
struct stat stb; struct stat stb;
/* looks like a good enough match to update the super block if needed */ /* looks like a good enough match to update the super block if needed */
@ -401,6 +441,18 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
if (strcmp(update, "uuid")==0 && if (strcmp(update, "uuid")==0 &&
ident->bitmap_fd) ident->bitmap_fd)
bitmap_update_uuid(ident->bitmap_fd, info.uuid); bitmap_update_uuid(ident->bitmap_fd, info.uuid);
} else {
int dfd;
dfd = dev_open(devname, O_RDWR|O_EXCL);
if (super) {
free(super);
super = NULL;
}
st->ss->load_super(st, dfd, &super, NULL);
st->ss->getinfo_super(&info, super);
close(dfd);
} }
stat(devname, &stb); stat(devname, &stb);

View File

@ -246,6 +246,7 @@ mddev_dev_t load_partitions(void)
d = malloc(sizeof(*d)); d = malloc(sizeof(*d));
d->devname = strdup(name); d->devname = strdup(name);
d->next = rv; d->next = rv;
d->used = 0;
rv = d; rv = d;
} }
fclose(f); fclose(f);
@ -716,6 +717,7 @@ mddev_dev_t conf_get_devs(char *conffile)
mddev_dev_t t = malloc(sizeof(*t)); mddev_dev_t t = malloc(sizeof(*t));
t->devname = strdup(globbuf.gl_pathv[i]); t->devname = strdup(globbuf.gl_pathv[i]);
t->next = dlist; t->next = dlist;
t->used = 0;
dlist = t; dlist = t;
/* printf("one dev is %s\n", t->devname);*/ /* printf("one dev is %s\n", t->devname);*/
} }

40
mdadm.c
View File

@ -237,6 +237,7 @@ int main(int argc, char *argv[])
dv->disposition = devmode; dv->disposition = devmode;
dv->writemostly = writemostly; dv->writemostly = writemostly;
dv->re_add = re_add; dv->re_add = re_add;
dv->used = 0;
dv->next = NULL; dv->next = NULL;
*devlistend = dv; *devlistend = dv;
devlistend = &dv->next; devlistend = &dv->next;
@ -981,10 +982,12 @@ int main(int argc, char *argv[])
} }
} else { } else {
mddev_ident_t array_list = conf_get_ident(configfile, NULL); mddev_ident_t array_list = conf_get_ident(configfile, NULL);
if (!array_list) { mddev_dev_t devlist = conf_get_devs(configfile);
fprintf(stderr, Name ": No arrays found in config file\n"); int cnt = 0;
rv = 1; if (devlist == NULL) {
} else fprintf(stderr, Name ": No devices listed in conf file were found.\n");
exit(1);
}
if (update) { if (update) {
fprintf(stderr, Name ": --update not meaningful with a --scan assembly.\n"); fprintf(stderr, Name ": --update not meaningful with a --scan assembly.\n");
exit(1); exit(1);
@ -1004,13 +1007,38 @@ int main(int argc, char *argv[])
if (ioctl(mdfd, GET_ARRAY_INFO, &array)>=0) if (ioctl(mdfd, GET_ARRAY_INFO, &array)>=0)
/* already assembled, skip */ /* already assembled, skip */
; ;
else else {
rv |= Assemble(ss, array_list->devname, mdfd, rv |= Assemble(ss, array_list->devname, mdfd,
array_list, configfile, array_list, configfile,
NULL, NULL, devlist, NULL,
readonly, runstop, NULL, homehost, verbose-quiet, force); readonly, runstop, NULL, homehost, verbose-quiet, force);
if (rv == 0) cnt++;
}
close(mdfd); close(mdfd);
} }
if (homehost) {
/* Maybe we can auto-assemble something.
* Repeatedly call Assemble in auto-assmble mode
* until it fails
*/
int rv2;
do {
ident.autof = autof;
rv2 = Assemble(ss, NULL, -1,
&ident, configfile,
devlist, NULL,
readonly, runstop, NULL, homehost, verbose-quiet, force);
if (rv2==0)
cnt++;
} while (rv2==0);
if (cnt == 0 && rv == 0) {
fprintf(stderr, Name ": No arrays found in config file or automatically\n");
rv = 1;
}
} else if (cnt == 0 && rv == 0) {
fprintf(stderr, Name ": No arrays found in config file\n");
rv = 1;
}
} }
break; break;
case BUILD: case BUILD: