summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Brown <neilb@suse.de>2006-05-26 00:50:15 +0000
committerNeil Brown <neilb@suse.de>2006-05-26 00:50:15 +0000
commitda6b5ca9bd6962ea70dfa750f3d85ac1657fb9cf (patch)
tree0a4e5847b4d2d1b8a73c7483e2c0ca26b3c1f1e4
parent8a46fe8487986f96e5313156336c02cc551282c8 (diff)
downloadmdadm-da6b5ca9bd6962ea70dfa750f3d85ac1657fb9cf.tar.gz
mdadm-da6b5ca9bd6962ea70dfa750f3d85ac1657fb9cf.tar.xz
mdadm-da6b5ca9bd6962ea70dfa750f3d85ac1657fb9cf.zip
Initial implementation of auto-assembly
This basically works, but needs various improvements and some tests. Signed-off-by: Neil Brown <neilb@suse.de>
-rw-r--r--Assemble.c68
-rw-r--r--config.c2
-rw-r--r--mdadm.c82
3 files changed, 117 insertions, 35 deletions
diff --git a/Assemble.c b/Assemble.c
index 46ec9bc..6d89a24 100644
--- a/Assemble.c
+++ b/Assemble.c
@@ -180,11 +180,15 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
}
if (devlist == NULL)
devlist = conf_get_devs(conffile);
- else inargv = 1;
+ else if (mdfd >= 0)
+ inargv = 1;
tmpdev = devlist; num_devs = 0;
while (tmpdev) {
- num_devs++;
+ if (tmpdev->used)
+ tmpdev->used = 2;
+ else
+ num_devs++;
tmpdev = tmpdev->next;
}
devices = malloc(num_devs * sizeof(*devices));
@@ -207,6 +211,8 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
struct stat stb;
struct supertype *tst = st;
+ if (tmpdev->used > 1) continue;
+
if (ident->devices &&
!match_oneof(ident->devices, devname)) {
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)
fprintf(stderr, Name ": cannot open device %s: %s\n",
devname, strerror(errno));
+ tmpdev->used = 2;
} else if (fstat(dfd, &stb)< 0) {
/* Impossible! */
fprintf(stderr, Name ": fstat failed for %s: %s\n",
devname, strerror(errno));
+ tmpdev->used = 2;
} else if ((stb.st_mode & S_IFMT) != S_IFBLK) {
fprintf(stderr, Name ": %s is not a block device.\n",
devname);
+ tmpdev->used = 2;
} else if (!tst && (tst = guess_super(dfd)) == NULL) {
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)) {
if ((inargv && verbose >= 0) || verbose > 0)
fprintf( stderr, Name ": no RAID superblock on %s\n",
@@ -278,7 +289,17 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
devname);
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 the super_block doesn't exist, or doesn't match others,
* 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->ss->compare_super(&first_super, super) != 0) {
/* 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) {
int first = st->ss->match_home(first_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
* superblock, and call open_mddev on that
*/
- asprintf(&mddev, "/dev/md/%s", info.name);
- mdfd = open_mddev(mddev, 0);
+ mdu_array_info_t inf;
+ 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)
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 */
- 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;
struct stat stb;
/* 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 &&
ident->bitmap_fd)
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);
diff --git a/config.c b/config.c
index 8382cdf..d753f54 100644
--- a/config.c
+++ b/config.c
@@ -246,6 +246,7 @@ mddev_dev_t load_partitions(void)
d = malloc(sizeof(*d));
d->devname = strdup(name);
d->next = rv;
+ d->used = 0;
rv = d;
}
fclose(f);
@@ -716,6 +717,7 @@ mddev_dev_t conf_get_devs(char *conffile)
mddev_dev_t t = malloc(sizeof(*t));
t->devname = strdup(globbuf.gl_pathv[i]);
t->next = dlist;
+ t->used = 0;
dlist = t;
/* printf("one dev is %s\n", t->devname);*/
}
diff --git a/mdadm.c b/mdadm.c
index 0df7369..6c30058 100644
--- a/mdadm.c
+++ b/mdadm.c
@@ -237,6 +237,7 @@ int main(int argc, char *argv[])
dv->disposition = devmode;
dv->writemostly = writemostly;
dv->re_add = re_add;
+ dv->used = 0;
dv->next = NULL;
*devlistend = dv;
devlistend = &dv->next;
@@ -981,36 +982,63 @@ int main(int argc, char *argv[])
}
} else {
mddev_ident_t array_list = conf_get_ident(configfile, NULL);
- if (!array_list) {
- fprintf(stderr, Name ": No arrays found in config file\n");
- rv = 1;
- } else
- if (update) {
- fprintf(stderr, Name ": --update not meaningful with a --scan assembly.\n");
- exit(1);
+ mddev_dev_t devlist = conf_get_devs(configfile);
+ int cnt = 0;
+ if (devlist == NULL) {
+ fprintf(stderr, Name ": No devices listed in conf file were found.\n");
+ exit(1);
+ }
+ if (update) {
+ fprintf(stderr, Name ": --update not meaningful with a --scan assembly.\n");
+ exit(1);
+ }
+ if (backup_file) {
+ fprintf(stderr, Name ": --backup_file not meaningful with a --scan assembly.\n");
+ exit(1);
+ }
+ for (; array_list; array_list = array_list->next) {
+ mdu_array_info_t array;
+ mdfd = open_mddev(array_list->devname,
+ array_list->autof ? array_list->autof : autof);
+ if (mdfd < 0) {
+ rv |= 1;
+ continue;
}
- if (backup_file) {
- fprintf(stderr, Name ": --backup_file not meaningful with a --scan assembly.\n");
- exit(1);
+ if (ioctl(mdfd, GET_ARRAY_INFO, &array)>=0)
+ /* already assembled, skip */
+ ;
+ else {
+ rv |= Assemble(ss, array_list->devname, mdfd,
+ array_list, configfile,
+ devlist, NULL,
+ readonly, runstop, NULL, homehost, verbose-quiet, force);
+ if (rv == 0) cnt++;
}
- for (; array_list; array_list = array_list->next) {
- mdu_array_info_t array;
- mdfd = open_mddev(array_list->devname,
- array_list->autof ? array_list->autof : autof);
- if (mdfd < 0) {
- rv |= 1;
- continue;
- }
- if (ioctl(mdfd, GET_ARRAY_INFO, &array)>=0)
- /* already assembled, skip */
- ;
- else
- rv |= Assemble(ss, array_list->devname, mdfd,
- array_list, configfile,
- NULL, NULL,
- readonly, runstop, NULL, homehost, verbose-quiet, force);
- 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;
case BUILD: