summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDoug Ledford <dledford@redhat.com>2008-10-29 14:23:49 -0400
committerDoug Ledford <dledford@redhat.com>2008-10-29 14:23:49 -0400
commitd3fbb3c40ab14707dde13cd297b7ac64d8c3109b (patch)
tree69274b5a1cd1aef2f7ccd12cdd34ad13d4e582f9
parentfb26614d7a69d164f9e401f57389a1ca4e84258f (diff)
downloadmdadm-d3fbb3c40ab14707dde13cd297b7ac64d8c3109b.tar.gz
mdadm-d3fbb3c40ab14707dde13cd297b7ac64d8c3109b.tar.xz
mdadm-d3fbb3c40ab14707dde13cd297b7ac64d8c3109b.zip
Make incremental mode work with partitionable arrays
There were multiple problems with incremental mode and partitionable arrays. Change the logic to pay more attention to what it finds in mdadm.conf when setting up incremental arrays. Modify is_standard to differentiate between a required partitioned name format and an optionally partitioned named format. Modify open_mddev() to know about change to is_standard. Make Incremental differentiate between create default autof setting, command line autof setting, and array specific autof setting, with order of preference being command line, conf file, default. Disable the homehost test in the event there is no match for an array so we can hotplug new arrays into a running machine without them having to exist in mdadm.conf first (a random array number will be picked for the hot plugged array). Honor any name from mdadm.conf that matches the UUID of a device, not just standard names. Verify that the array name as matched in mdadm.conf allows the requested mode of operation and reject attempts to start non-partitionable arrays as partitioned and vice versa. Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r--Incremental.c122
-rw-r--r--mdopen.c4
-rw-r--r--util.c2
3 files changed, 117 insertions, 11 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, ':');
diff --git a/mdopen.c b/mdopen.c
index 4fbcb48..4ba6fff 100644
--- a/mdopen.c
+++ b/mdopen.c
@@ -147,8 +147,8 @@ int open_mddev(char *dev, int autof)
return -1;
}
break;
- case 3: /* create md, reject std>0 */
- if (std > 0) {
+ case 3: /* create md, reject std==1 */
+ if (std == 1) {
fprintf(stderr, Name ": that --auto option "
"not compatable with device named %s\n", dev);
return -1;
diff --git a/util.c b/util.c
index 75f3706..baa1690 100644
--- a/util.c
+++ b/util.c
@@ -396,7 +396,7 @@ int is_standard(char *dev, int *nump)
if (!d)
return 0;
if (strncmp(d, "/d",2)==0)
- d += 2, type=1; /* /dev/md/dN{pM} */
+ d += 2, type=2; /* /dev/md/dN{pM} */
else if (strncmp(d, "/md_d", 5)==0)
d += 5, type=1; /* /dev/md_dNpM */
else if (strncmp(d, "/md", 3)==0)