summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Brown <neilb@suse.de>2006-05-23 06:12:40 +0000
committerNeil Brown <neilb@suse.de>2006-05-23 06:12:40 +0000
commit811e6cbed7cc06e6946e4a851710fb1e8cb36fd5 (patch)
treedd421f0cc8b2d20ccf1253827efdee7c5df8869b
parent624920bbb60dafac5719ee42225a3fba9f8464de (diff)
downloadmdadm-811e6cbed7cc06e6946e4a851710fb1e8cb36fd5.tar.gz
mdadm-811e6cbed7cc06e6946e4a851710fb1e8cb36fd5.tar.xz
mdadm-811e6cbed7cc06e6946e4a851710fb1e8cb36fd5.zip
Reorganise Assemble code somewhat.
We make sure all devices can are consistent before doing any --update This saves us from updating some but not all of an array, and then aborting. It also means we can backtrack on out decisions, which we might want to do later. Signed-off-by: Neil Brown <neilb@suse.de>
-rw-r--r--Assemble.c37
-rw-r--r--mdadm.h1
2 files changed, 31 insertions, 7 deletions
diff --git a/Assemble.c b/Assemble.c
index d35aa5a..ecee624 100644
--- a/Assemble.c
+++ b/Assemble.c
@@ -193,15 +193,18 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
fprintf(stderr, Name ": looking for devices for %s\n",
mddev);
- while ( devlist) {
- char *devname;
+ /* first walk the list of devices to find a consistent set
+ * that match the criterea, if that is possible.
+ * We flag the one we like with 'used'.
+ */
+ for (tmpdev = devlist;
+ tmpdev;
+ tmpdev = tmpdev->next) {
+ char *devname = tmpdev->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>=0) || verbose > 0)
@@ -296,12 +299,19 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
return 1;
}
+ tmpdev->used = 1;
+ }
+
+ /* Ok, no bad inconsistancy, we can try updating etc */
+ for (tmpdev = devlist; tmpdev; tmpdev=tmpdev->next) if (tmpdev->used) {
+ char *devname = tmpdev->devname;
+ struct stat stb;
/* looks like a good enough match to update the super block if needed */
if (update) {
+ int dfd;
/* prepare useful information in info structures */
struct stat stb2;
fstat(mdfd, &stb2);
- info.array.md_minor = minor(stb2.st_rdev);
if (strcmp(update, "uuid")==0 &&
!ident->uuid_set) {
@@ -315,8 +325,20 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
}
if (rfd >= 0) close(rfd);
}
+ 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);
+
memcpy(info.uuid, ident->uuid, 16);
strcpy(info.name, ident->name);
+ info.array.md_minor = minor(stb2.st_rdev);
+
st->ss->update_super(&info, super, update, devname, verbose,
ident->uuid_set, homehost);
if (strcmp(update, "uuid")==0 &&
@@ -324,7 +346,6 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
ident->uuid_set = 1;
memcpy(ident->uuid, info.uuid, 16);
}
- dfd = dev_open(devname, O_RDWR|O_EXCL);
if (dfd < 0)
fprintf(stderr, Name ": Cannot open %s for superblock update\n",
devname);
@@ -339,6 +360,8 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
bitmap_update_uuid(ident->bitmap_fd, info.uuid);
}
+ stat(devname, &stb);
+
if (verbose > 0)
fprintf(stderr, Name ": %s is identified as a member of %s, slot %d.\n",
devname, mddev, info.disk.raid_disk);
diff --git a/mdadm.h b/mdadm.h
index ecaacd4..94e4708 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -182,6 +182,7 @@ typedef struct mddev_dev_s {
*/
char writemostly;
char re_add;
+ char used; /* set when used */
struct mddev_dev_s *next;
} *mddev_dev_t;