diff --git a/Assemble.c b/Assemble.c index 47b8839..4966a79 100644 --- a/Assemble.c +++ b/Assemble.c @@ -263,6 +263,13 @@ int Assemble(struct supertype *st, char *mddev, fprintf(stderr, Name ": no recogniseable superblock on %s\n", devname); tmpdev->used = 2; + } else if (auto_assem && st == NULL && + !conf_test_metadata(tst->ss->name)) { + if (report_missmatch) + fprintf(stderr, Name ": %s has metadata type %s for which " + "auto-assembly is disabled\n", + devname, tst->ss->name); + tmpdev->used = 2; } else if (tst->ss->load_super(tst,dfd, NULL)) { if (report_missmatch) fprintf( stderr, Name ": no RAID superblock on %s\n", diff --git a/Incremental.c b/Incremental.c index 5849d39..7d6de98 100644 --- a/Incremental.c +++ b/Incremental.c @@ -220,6 +220,15 @@ int Incremental(char *devname, int verbose, int runstop, return 1; } + if (!match && !conf_test_metadata(st->ss->name)) { + if (verbose >= 1) + fprintf(stderr, Name + ": %s has metadata type %s for which " + "auto-assembly is disabled\n", + devname, st->ss->name); + return 1; + } + /* 3a/ if not, check for homehost match. If no match, continue * but don't trust the 'name' in the array. Thus a 'random' minor * number will be assigned, and the device name will be based diff --git a/config.c b/config.c index 66c3964..0d5b3f9 100644 --- a/config.c +++ b/config.c @@ -56,7 +56,7 @@ * with a key word, and not be indented, or must start with a * non-key-word and must be indented. * - * Keywords are DEVICE and ARRAY + * Keywords are DEVICE and ARRAY ... and several others. * DEV{ICE} introduces some devices that might contain raid components. * e.g. * DEV style=0 /dev/sda* /dev/hd* @@ -79,7 +79,8 @@ char DefaultConfFile[] = CONFFILE; char DefaultAltConfFile[] = CONFFILE2; -enum linetype { Devices, Array, Mailaddr, Mailfrom, Program, CreateDev, Homehost, LTEnd }; +enum linetype { Devices, Array, Mailaddr, Mailfrom, Program, CreateDev, + Homehost, AutoMode, LTEnd }; char *keywords[] = { [Devices] = "devices", [Array] = "array", @@ -88,6 +89,7 @@ char *keywords[] = { [Program] = "program", [CreateDev]= "create", [Homehost] = "homehost", + [AutoMode] = "auto", [LTEnd] = NULL }; @@ -639,6 +641,16 @@ void homehostline(char *line) } } +static char *auto_options = NULL; +void autoline(char *line) +{ + if (auto_options) { + fprintf(stderr, Name ": AUTO line may only be give once." + " Subsequent lines ignored\n"); + return; + } + auto_options = line; +} int loaded = 0; @@ -709,6 +721,9 @@ void load_conffile(void) case Homehost: homehostline(line); break; + case AutoMode: + autoline(line); + break; default: fprintf(stderr, Name ": Unknown keyword %s\n", line); } @@ -832,6 +847,52 @@ int conf_test_dev(char *devname) return 0; } +int conf_test_metadata(const char *version) +{ + /* Check if the given metadata version is allowed + * to be auto-assembled. + * The default is 'yes' but the 'auto' line might over-ride that. + * Word in auto_options are processed in order with the first + * match winning. + * word can be: + * +version - that version can be assembled + * -version - that version cannot be auto-assembled + * yes or +all - any other version can be assembled + * no or -all - no other version can be assembled. + */ + char *w; + load_conffile(); + if (!auto_options) + return 1; + for (w = dl_next(auto_options); w != auto_options; w = dl_next(w)) { + int rv; + if (strcasecmp(w, "yes") == 0) + return 1; + if (strcasecmp(w, "no") == 0) + return 0; + if (w[0] == '+') + rv = 1; + else if (w[0] == '-') + rv = 0; + else continue; + + if (strcasecmp(w+1, "all") == 0) + return rv; + if (strcasecmp(w+1, version) == 0) + return rv; + /* allow '0' to match version '0.90' + * and 1 or 1.whatever to match version '1.x' + */ + if (version[1] == '.' && + strlen(w+1) == 1 && + w[1] == version[0]) + return rv; + if (version[1] == '.' && version[2] == 'x' && + strncmp(w+1, version, 2) == 0) + return rv; + } + return 1; +} int match_oneof(char *devices, char *devname) { diff --git a/mdadm.conf.5 b/mdadm.conf.5 index 7654f5f..f69c0b0 100644 --- a/mdadm.conf.5 +++ b/mdadm.conf.5 @@ -339,6 +339,39 @@ 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. +.TP +.B AUTO +A list of names of metadata format can be given, each preceded by a +plus or minus sign. Also the word +.I all +preceded by plus or minus is allowed and is usually last. + +When +.I mdadm +is auto-assembling an array, with via +.I --assemble +or +.I --incremental +and it finds metadata of a given type, it checks that metadata type +against those listed in this line. The first match wins, where +.I all +matches anything. +If a match is found that was preceded by a plus sign, the auto +assembly is allowed. If the match was preceded by a minus sign, the +auto assembly is disallowed. If no match is found, the auto assembly +is allowed. + +This can be used to disable all auto-assembly (so that only arrays +explicitly listed in mdadm.conf or on the command line are assembled), +or to disable assembly of certain metadata types which might be +handled by other software. + +The known metadata types are +.BR 0.90 , +.BR 1.x , +.BR ddf , +.BR imsm . + .SH EXAMPLE DEVICE /dev/sd[bcdjkl]1 .br @@ -385,6 +418,8 @@ PROGRAM /usr/sbin/handle\-mdadm\-events CREATE group=system mode=0640 auto=part\-8 .br HOMEHOST +.br +AUTO +1.x -all .SH SEE ALSO .BR mdadm (8), diff --git a/mdadm.h b/mdadm.h index 251f9a1..1f47be3 100644 --- a/mdadm.h +++ b/mdadm.h @@ -789,6 +789,7 @@ extern int parse_auto(char *str, char *msg, int config); extern mddev_ident_t conf_get_ident(char *dev); extern mddev_dev_t conf_get_devs(void); extern int conf_test_dev(char *devname); +extern int conf_test_metadata(const char *version); extern struct createinfo *conf_get_create_info(void); extern void set_conffile(char *file); extern char *conf_get_mailaddr(void); diff --git a/super1.c b/super1.c index d1b8a94..679120f 100644 --- a/super1.c +++ b/super1.c @@ -1652,5 +1652,5 @@ struct superswitch super1 = { #else .swapuuid = 1, #endif - .name = "1.0", + .name = "1.x", };