diff options
author | Neil Brown <neilb@suse.de> | 2006-05-23 08:33:28 +0200 |
---|---|---|
committer | Neil Brown <neilb@suse.de> | 2006-05-23 08:33:28 +0200 |
commit | 83b6208e890f29115c56a252de82dfd7c50488d0 (patch) | |
tree | ccf7ab891b274cc805602a6400ee2736c03101a6 | |
parent | Reorganise Assemble code somewhat. (diff) | |
download | 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.c | 40 | ||||
-rw-r--r-- | mdadm.h | 1 | ||||
-rw-r--r-- | super0.c | 12 | ||||
-rw-r--r-- | super1.c | 11 |
4 files changed, 59 insertions, 5 deletions
@@ -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); @@ -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); @@ -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, @@ -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, |