summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Brown <neilb@suse.de>2006-05-23 06:33:28 +0000
committerNeil Brown <neilb@suse.de>2006-05-23 06:33:28 +0000
commit83b6208e890f29115c56a252de82dfd7c50488d0 (patch)
treeccf7ab891b274cc805602a6400ee2736c03101a6
parent811e6cbed7cc06e6946e4a851710fb1e8cb36fd5 (diff)
downloadmdadm-83b6208e890f29115c56a252de82dfd7c50488d0.tar.gz
mdadm-83b6208e890f29115c56a252de82dfd7c50488d0.tar.xz
mdadm-83b6208e890f29115c56a252de82dfd7c50488d0.zip
When assembly arrays using incomplete detail, prefer arrays built for this host.
i.e. if assembling with --name or --super-minor, then if we find two different arrays with the same apparent identity, and one was built for 'this' host, then prefer that one instead of giving up in disgust. Signed-off-by: Neil Brown <neilb@suse.de>
-rw-r--r--Assemble.c40
-rw-r--r--mdadm.h1
-rw-r--r--super0.c12
-rw-r--r--super1.c11
4 files changed, 59 insertions, 5 deletions
diff --git a/Assemble.c b/Assemble.c
index ecee624..4516b62 100644
--- a/Assemble.c
+++ b/Assemble.c
@@ -277,9 +277,11 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
continue;
}
- /* If we are this far, then we are 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,
- * then we cannot continue
+ * then we probably cannot continue
+ * However if one of the arrays is for the homehost, and
+ * the other isn't that can disambiguate.
*/
if (!super) {
@@ -289,9 +291,37 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
return 1;
}
-
- st = tst; /* commit to this format, if haven't already */
- if (st->ss->compare_super(&first_super, super)) {
+ if (st == NULL)
+ st = tst;
+ if (st->ss != tst->ss ||
+ 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
+ */
+ if (homehost) {
+ int first = st->ss->match_home(first_super, homehost);
+ int last = tst->ss->match_home(super, homehost);
+ if (first+last == 1) {
+ /* We can do something */
+ if (first) {/* just ignore this one */
+ if ((inargv && verbose >= 0) || verbose > 0)
+ fprintf(stderr, Name ": %s misses out due to wrong homehost\n",
+ devname);
+ continue;
+ } else { /* reject all those sofar */
+ mddev_dev_t td;
+ if ((inargv && verbose >= 0) || verbose > 0)
+ fprintf(stderr, Name ": %s overrides previous devices due to good homehost\n",
+ devname);
+ for (td=devlist; td != tmpdev; td=td->next)
+ if (td->used == 1)
+ td->used = 0;
+ tmpdev->used = 1;
+ continue;
+ }
+ }
+ }
fprintf(stderr, Name ": superblock on %s doesn't match others - assembly aborted\n",
devname);
free(super);
diff --git a/mdadm.h b/mdadm.h
index 94e4708..7fc3bed 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -279,6 +279,7 @@ extern struct superswitch {
void (*brief_detail_super)(void *sbv);
void (*uuid_from_super)(int uuid[4], void *sbv);
void (*getinfo_super)(struct mdinfo *info, void *sbv);
+ int (*match_home)(void *sbv, char *homehost);
int (*update_super)(struct mdinfo *info, void *sbv, char *update,
char *devname, int verbose,
int uuid_set, char *homehost);
diff --git a/super0.c b/super0.c
index 85e54fc..cc2f7a9 100644
--- a/super0.c
+++ b/super0.c
@@ -269,6 +269,17 @@ static void brief_detail_super0(void *sbv)
printf("%08x", sb->set_uuid0);
}
#endif
+
+static int match_home0(void *sbv, char *homehost)
+{
+ mdp_super_t *sb = sbv;
+ unsigned char *hash = SHA1((unsigned char *)homehost,
+ strlen(homehost),
+ NULL);
+
+ return (memcmp(&sb->set_uuid2, hash, 8)==0);
+}
+
static void uuid_from_super0(int uuid[4], void * sbv)
{
mdp_super_t *super = sbv;
@@ -942,6 +953,7 @@ struct superswitch super0 = {
.detail_super = detail_super0,
.brief_detail_super = brief_detail_super0,
#endif
+ .match_home = match_home0,
.uuid_from_super = uuid_from_super0,
.getinfo_super = getinfo_super0,
.update_super = update_super0,
diff --git a/super1.c b/super1.c
index b24bcea..488aabe 100644
--- a/super1.c
+++ b/super1.c
@@ -357,6 +357,16 @@ static void brief_detail_super1(void *sbv)
#endif
+static int match_home1(void *sbv, char *homehost)
+{
+ struct mdp_superblock_1 *sb = sbv;
+ int l = homehost ? strlen(homehost) : 0;
+
+ return (l > 0 && l < 32 &&
+ sb->set_name[l] == ':' &&
+ strncmp(sb->set_name, homehost, l) == 0);
+}
+
static void uuid_from_super1(int uuid[4], void * sbv)
{
struct mdp_superblock_1 *super = sbv;
@@ -1191,6 +1201,7 @@ struct superswitch super1 = {
.detail_super = detail_super1,
.brief_detail_super = brief_detail_super1,
#endif
+ .match_home = match_home1,
.uuid_from_super = uuid_from_super1,
.getinfo_super = getinfo_super1,
.update_super = update_super1,