From 0ac91628b93b31636979b637c1ac7258064dea4e Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 11 May 2009 15:46:46 +1000 Subject: [PATCH] Allow homehost to be largely ignored when assembling arrays. If mdadm.conf contains HOMEHOST or commandline contains --homehost= then the check that array metadata mentions the given homehost is replace by a check that the name recorded in the metadata is not already used by some other array mentioned in mdadm.conf. This allows more arrays to use their native name rather than having an _NN suffix added. This should only be used during boot time if all arrays required for normal boot are listed in mdadm.conf. If auto-assembly is used to find all array during boot, then the HOMEHOST feature should be used to ensure there is no room for confusion in choosing array names, and so it should not be set to . Signed-off-by: NeilBrown --- Assemble.c | 8 ++++++- Incremental.c | 11 ++++++--- config.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++-- mdadm.8 | 3 ++- mdadm.c | 34 +++++++++++++++++++-------- mdadm.conf.5 | 24 +++++++++++++++---- mdadm.h | 10 +++++--- mdassemble.c | 3 ++- 8 files changed, 132 insertions(+), 25 deletions(-) diff --git a/Assemble.c b/Assemble.c index c079f6b3..2c52f074 100644 --- a/Assemble.c +++ b/Assemble.c @@ -79,7 +79,7 @@ int Assemble(struct supertype *st, char *mddev, mddev_ident_t ident, mddev_dev_t devlist, char *backup_file, int readonly, int runstop, - char *update, char *homehost, + char *update, char *homehost, int require_homehost, int verbose, int force) { /* @@ -509,6 +509,12 @@ int Assemble(struct supertype *st, char *mddev, name = content->text_version; trustworthy = METADATA; } + + if (name[0] && trustworthy != LOCAL && + ! require_homehost && + conf_name_is_free(name)) + trustworthy = LOCAL; + mdfd = create_mddev(mddev, name, ident->autof, trustworthy, chosen_name); if (mdfd < 0) { diff --git a/Incremental.c b/Incremental.c index 8908eece..c5ec6340 100644 --- a/Incremental.c +++ b/Incremental.c @@ -37,7 +37,8 @@ static void find_reject(int mdfd, struct supertype *st, struct mdinfo *sra, char *array_name); int Incremental(char *devname, int verbose, int runstop, - struct supertype *st, char *homehost, int autof) + struct supertype *st, char *homehost, int require_homehost, + int autof) { /* Add this device to an array, creating the array if necessary * and starting the array if sensible or - if runstop>0 - if possible. @@ -265,12 +266,16 @@ int Incremental(char *devname, int verbose, int runstop, else name_to_use = info.name; - if ((!name_to_use || name_to_use[0] == 0) && + if (name_to_use[0] == 0 && info.array.level == LEVEL_CONTAINER && trustworthy == LOCAL) { name_to_use = info.text_version; trustworthy = METADATA; } + if (name_to_use[0] && trustworthy != LOCAL && + ! require_homehost && + conf_name_is_free(name_to_use)) + trustworthy = LOCAL; /* 4/ Check if array exists. */ @@ -424,7 +429,7 @@ int Incremental(char *devname, int verbose, int runstop, if (runstop < 0) return 0; /* don't try to assemble */ rv = Incremental(chosen_name, verbose, runstop, - NULL, homehost, autof); + NULL, homehost, require_homehost, autof); if (rv == 1) /* Don't fail the whole -I if a subarray didn't * have enough devices to start yet diff --git a/config.c b/config.c index 41428ae9..284896ed 100644 --- a/config.c +++ b/config.c @@ -663,12 +663,15 @@ void programline(char *line) } static char *home_host = NULL; +static int require_homehost = 1; void homehostline(char *line) { char *w; for (w=dl_next(line); w != line ; w=dl_next(w)) { - if (home_host == NULL) + if (strcasecmp(w, "")==0) + require_homehost = 0; + else if (home_host == NULL) home_host = strdup(w); else fprintf(stderr, Name ": excess host name on HOMEHOST line: %s - ignored\n", @@ -788,9 +791,11 @@ char *conf_get_program(void) return alert_program; } -char *conf_get_homehost(void) +char *conf_get_homehost(int *require_homehostp) { load_conffile(); + if (require_homehostp) + *require_homehostp = require_homehost; return home_host; } @@ -953,3 +958,58 @@ int match_oneof(char *devices, char *devname) } return 0; } + +int devname_matches(char *name, char *match) +{ + /* See if the given array name matches the + * given match from config file. + * + * First strip and /dev/md/ or /dev/, then + * see if there might be a numeric match of + * mdNN with NN + * then just strcmp + */ + if (strncmp(name, "/dev/md/", 8) == 0) + name += 8; + else if (strncmp(name, "/dev/", 5) == 0) + name += 5; + + if (strncmp(match, "/dev/md/", 8) == 0) + match += 8; + else if (strncmp(match, "/dev/", 5) == 0) + match += 5; + + + if (strncmp(name, "md", 2) == 0 && + isdigit(name[2])) + name += 2; + if (strncmp(match, "md", 2) == 0 && + isdigit(match[2])) + match += 2; + + return (strcmp(name, match) == 0); +} + +int conf_name_is_free(char *name) +{ + /* Check if this name is already take by an ARRAY entry in + * the config file. + * It can be taken either by a match on devname, name, or + * even super-minor. + */ + mddev_ident_t dev; + + load_conffile(); + for (dev = mddevlist; dev; dev = dev->next) { + char nbuf[100]; + if (dev->devname && devname_matches(name, dev->devname)) + return 0; + if (dev->name[0] && devname_matches(name, dev->name)) + return 0; + sprintf(nbuf, "%d", dev->super_minor); + if (dev->super_minor != UnSet && + devname_matches(name, nbuf)) + return 0; + } + return 1; +} diff --git a/mdadm.8 b/mdadm.8 index 04fea60d..58270fa6 100644 --- a/mdadm.8 +++ b/mdadm.8 @@ -357,7 +357,8 @@ When reporting information about an array, any array which is tagged for the given homehost will be reported as such. When using Auto-Assemble, only arrays tagged for the given homehost -will be assembled. +will be allowed to use 'local' names (i.e. not ending in '_' followed +by a digit string). .SH For create, build, or grow: diff --git a/mdadm.c b/mdadm.c index 3245f0f7..74d230e3 100644 --- a/mdadm.c +++ b/mdadm.c @@ -91,6 +91,7 @@ int main(int argc, char *argv[]) char *homehost = NULL; char sys_hostname[256]; + int require_homehost = 1; char *mailaddr = NULL; char *program = NULL; int delay = 0; @@ -166,7 +167,10 @@ int main(int argc, char *argv[]) continue; case HomeHost: - homehost = optarg; + if (strcasecmp(optarg, "") == 0) + require_homehost = 0; + else + homehost = optarg; continue; case ':': @@ -1009,7 +1013,7 @@ int main(int argc, char *argv[]) } if (homehost == NULL) - homehost = conf_get_homehost(); + homehost = conf_get_homehost(&require_homehost); if (homehost == NULL || strcmp(homehost, "")==0) { if (gethostname(sys_hostname, sizeof(sys_hostname)) == 0) { sys_hostname[sizeof(sys_hostname)-1] = 0; @@ -1049,12 +1053,16 @@ int main(int argc, char *argv[]) array_ident->autof = autof; rv |= Assemble(ss, devlist->devname, array_ident, NULL, backup_file, - readonly, runstop, update, homehost, verbose-quiet, force); + readonly, runstop, update, + homehost, require_homehost, + verbose-quiet, force); } } else if (!scan) rv = Assemble(ss, devlist->devname, &ident, devlist->next, backup_file, - readonly, runstop, update, homehost, verbose-quiet, force); + readonly, runstop, update, + homehost, require_homehost, + verbose-quiet, force); else if (devs_found>0) { if (update && devs_found > 1) { fprintf(stderr, Name ": can only update a single array at a time\n"); @@ -1076,7 +1084,9 @@ int main(int argc, char *argv[]) array_ident->autof = autof; rv |= Assemble(ss, dv->devname, array_ident, NULL, backup_file, - readonly, runstop, update, homehost, verbose-quiet, force); + readonly, runstop, update, + homehost, require_homehost, + verbose-quiet, force); } } else { mddev_ident_t array_list = conf_get_ident(NULL); @@ -1104,7 +1114,9 @@ int main(int argc, char *argv[]) rv |= Assemble(ss, array_list->devname, array_list, NULL, NULL, - readonly, runstop, NULL, homehost, verbose-quiet, force); + readonly, runstop, NULL, + homehost, require_homehost, + verbose-quiet, force); cnt++; } if (homehost && cnt == 0) { @@ -1122,7 +1134,9 @@ int main(int argc, char *argv[]) rv2 = Assemble(ss, NULL, &ident, devlist, NULL, - readonly, runstop, NULL, homehost, verbose-quiet, force); + readonly, runstop, NULL, + homehost, require_homehost, + verbose-quiet, force); if (rv2==0) { cnt++; acnt++; @@ -1143,7 +1157,9 @@ int main(int argc, char *argv[]) rv2 = Assemble(ss, NULL, &ident, NULL, NULL, - readonly, runstop, "homehost", homehost, verbose-quiet, force); + readonly, runstop, "homehost", + homehost, require_homehost, + verbose-quiet, force); if (rv2==0) { cnt++; acnt++; @@ -1410,7 +1426,7 @@ int main(int argc, char *argv[]) break; } rv = Incremental(devlist->devname, verbose-quiet, runstop, - ss, homehost, autof); + ss, homehost, require_homehost, autof); break; case AUTODETECT: autodetect(); diff --git a/mdadm.conf.5 b/mdadm.conf.5 index 9876d279..7ef1765a 100644 --- a/mdadm.conf.5 +++ b/mdadm.conf.5 @@ -333,18 +333,32 @@ The line gives a default value for the .B --homehost= option to mdadm. There should be exactly one other word on the line. -It should either exactly +It should either be a host name, or one of the special words .B -or a host name. +and +.BR . If .B is given, then the .BR gethostname ( 2 ) systemcall is used to get the host name. -When arrays are created, this host name will be stored in the -metadata. When arrays are assembled using auto-assembly, only arrays -with this host name stored in the metadata will be considered. +If +.B +is given, then a flag is set so that when arrays are being +auto-assemble the checking of the recorded +.I homehost +is disabled. + +When arrays are created, this host name will be stored in the +metadata. When arrays are assembled using auto-assembly, arrays which +do not record the correct homehost name in their metadata will be +assembled using a 'foreign' name. A 'foreign' name alway ends with a +digit string (possibly preceded by an underscore) to differentiate it +from any possible local name. e.g. +.B /dev/md/1_1 +or +.BR /dev/md/home0 . .TP .B AUTO A list of names of metadata format can be given, each preceded by a diff --git a/mdadm.h b/mdadm.h index d9bb4c9c..645cf589 100644 --- a/mdadm.h +++ b/mdadm.h @@ -724,7 +724,7 @@ extern int Assemble(struct supertype *st, char *mddev, mddev_ident_t ident, mddev_dev_t devlist, char *backup_file, int readonly, int runstop, - char *update, char *homehost, + char *update, char *homehost, int require_homehost, int verbose, int force); extern int Build(char *mddev, int chunk, int level, int layout, @@ -755,7 +755,8 @@ extern int Wait(char *dev); extern int WaitClean(char *dev, int verbose); extern int Incremental(char *devname, int verbose, int runstop, - struct supertype *st, char *homehost, int autof); + struct supertype *st, char *homehost, int require_homehost, + int autof); extern int Incremental_container(struct supertype *st, char *devname, int verbose, int runstop, int autof, int trustworthy); @@ -795,9 +796,12 @@ extern void set_conffile(char *file); extern char *conf_get_mailaddr(void); extern char *conf_get_mailfrom(void); extern char *conf_get_program(void); -extern char *conf_get_homehost(void); +extern char *conf_get_homehost(int *require_homehostp); extern char *conf_line(FILE *file); extern char *conf_word(FILE *file, int allow_key); +extern int conf_name_is_free(char *name); +extern int devname_matches(char *name, char *match); + extern void free_line(char *line); extern int match_oneof(char *devices, char *devname); extern void uuid_from_super(int uuid[4], mdp_super_t *super); diff --git a/mdassemble.c b/mdassemble.c index e2baf055..45ff9c57 100644 --- a/mdassemble.c +++ b/mdassemble.c @@ -111,7 +111,8 @@ int main(int argc, char *argv[]) { close(mdfd); rv |= Assemble(array_list->st, array_list->devname, array_list, NULL, NULL, - readonly, runstop, NULL, NULL, verbose, force); + readonly, runstop, NULL, NULL, 0, + verbose, force); } return rv; } -- 2.39.2