From 83b6208e890f29115c56a252de82dfd7c50488d0 Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Tue, 23 May 2006 06:33:28 +0000 Subject: [PATCH] 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 --- Assemble.c | 40 +++++++++++++++++++++++++++++++++++----- mdadm.h | 1 + super0.c | 12 ++++++++++++ super1.c | 11 +++++++++++ 4 files changed, 59 insertions(+), 5 deletions(-) diff --git a/Assemble.c b/Assemble.c index ecee624a..4516b62c 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 94e47085..7fc3bedd 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 85e54fc9..cc2f7a95 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 b24bceae..488aabe1 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, -- 2.39.2