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:
parent
8a46fe8487
commit
da6b5ca9bd
66
Assemble.c
66
Assemble.c
|
@ -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);
|
||||||
|
|
2
config.c
2
config.c
|
@ -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
40
mdadm.c
|
@ -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:
|
||||||
|
|
Loading…
Reference in New Issue