diff options
Diffstat (limited to 'Incremental.c')
-rw-r--r-- | Incremental.c | 122 |
1 files changed, 114 insertions, 8 deletions
diff --git a/Incremental.c b/Incremental.c index 9c6524f..806d192 100644 --- a/Incremental.c +++ b/Incremental.c @@ -87,9 +87,6 @@ int Incremental(char *devname, int verbose, int runstop, struct createinfo *ci = conf_get_create_info(); - if (autof == 0) - autof = ci->autof; - /* 1/ Check if devices is permitted by mdadm.conf */ if (!conf_test_dev(devname)) { @@ -204,6 +201,10 @@ int Incremental(char *devname, int verbose, int runstop, } /* 3a/ if not, check for homehost match. If no match, reject. */ + /* We want to support hot plugged arrays that aren't listed in + * /etc/mdadm.conf, so we need to skip the homehost test and allow + * unmatched devices through so we can simply pick a random entry + * to start them under if (!match) { if (homehost == NULL || st->ss->match_home(st, homehost) == 0) { @@ -212,23 +213,128 @@ int Incremental(char *devname, int verbose, int runstop, ": not found in mdadm.conf and not identified by homehost.\n"); return 2; } - } + } */ /* 4/ Determine device number. */ - /* - If in mdadm.conf with std name, use that */ + /* - If in mdadm.conf with any name, use that */ /* - UUID in /var/run/mdadm.map use that */ /* - If name is suggestive, use that. unless in use with */ /* different uuid. */ /* - Choose a free, high number. */ /* - Use a partitioned device unless strong suggestion not to. */ /* e.g. auto=md */ - if (match && is_standard(match->devname, &devnum)) - /* We have devnum now */; - else if ((mp = map_by_uuid(&map, info.uuid)) != NULL) + if (match) { + int use_partitions; + if (autof != 0) + /* command line overrides config file */ + match->autof = autof; + else if (match->autof == 0) + /* no specific autof setting in config for this */ + /* array, so use the ci->autof instead */ + match->autof = ci->autof; + switch(is_standard(match->devname, &devnum)) { + case 0: /* non-standard name */ + /* Need to find a free devnum to use */ + /* Need to know if we are supposed to be partitioned */ + /* or not to find a free devnum in the right major */ + switch(match->autof & 0x7) { + case 3: + case 5: + autof = match->autof; + case 0: /* this is what you get when you */ + /* don't specify anything, leave it */ + /* defaulting to non-partitioned for */ + /* back compatibility */ + use_partitions = 0; + break; + default: + autof = match->autof; + use_partitions = 1; + } + /* If we already have an assigned devnum find it */ + if ((mp = map_by_uuid(&map, info.uuid)) != NULL) + devnum = mp->devnum; + else + devnum = find_free_devnum(use_partitions); + + if (devnum == NoMdDev) { + fprintf(stderr, Name + ": No spare md devices!!\n"); + return 2; + } + break; + case -1: /* standard, non-partitioned name */ + switch(match->autof & 0x7) { + case 3: + case 5: + case 0: + /* all good */ + use_partitions = 0; + break; + default: + /* oops, attempting to set things to */ + /* an invalid state */ + fprintf(stderr, Name + ": can't be a partitioned device by naming standards!!\n"); + return 2; + } + break; + case 1: /* standard, partitioned name */ + switch(match->autof & 0x7) { + case 3: + case 5: + /* oops, attempting to set things to */ + /* an invalid state */ + fprintf(stderr, Name + ": must be a partitioned device by naming standards!!\n"); + return 2; + case 0: + /* we haven't been told how many */ + /* partitions to make on either the */ + /* command line or the config file, */ + /* set to the default and enable */ + /* partitioned mode due to our name */ + autof = match->autof = (4 << 3) | 2; + default: + /* all good */ + use_partitions = 1; + break; + } + break; + case 2: /* may be either partitioned or not, devnum is set */ + switch(match->autof & 0x7) { + case 0: + /* not specified in any way, default to */ + /* unpartitioned for back compatibility */ + case 1: + case 3: + case 5: + use_partitions = 0; + break; + case 2: + /* partitioned, but we didn't get a number */ + /* of parititions, so use the default */ + match->autof = autof |= 4 << 3; + case 4: + case 6: + /* the number of partitions is already in */ + /* autof */ + use_partitions = 1; + break; + } + break; + } + /* We have devnum now */ + if (use_partitions && devnum > 0) + devnum = (-1-devnum); + } else if ((mp = map_by_uuid(&map, info.uuid)) != NULL) devnum = mp->devnum; else { /* Have to guess a bit. */ int use_partitions = 1; char *np, *ep; + + if (autof == 0 && ci->autof) + autof = ci->autof; if ((autof&7) == 3 || (autof&7) == 5) use_partitions = 0; np = strchr(info.name, ':'); |