From eca944fa9ca52b24d0aa4d1034066bbd148e529a Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 15 May 2013 11:03:25 +1000 Subject: [PATCH] create_mddev: add support for /dev/md_XXX non-numeric names. With the 'devnm' infrastructure fixed, it is quite easy to support names like "md_home" for md arrays. The currently defaults to "off" and can be enabled in mdadm.conf with CREATE names=yes This is incase other tools get confused by the new names. Signed-off-by: NeilBrown --- Create.c | 6 +++--- config.c | 5 +++++ mdadm.8.in | 28 +++++++++++++++++++------- mdadm.conf.5 | 32 +++++++++++++++++++++++++++--- mdadm.h | 1 + mdopen.c | 55 +++++++++++++++++++++++++++++++++------------------- 6 files changed, 94 insertions(+), 33 deletions(-) diff --git a/Create.c b/Create.c index 63d50d6..e7ed09b 100644 --- a/Create.c +++ b/Create.c @@ -687,6 +687,7 @@ int Create(struct supertype *st, char *mddev, /* base name on mddev */ /* /dev/md0 -> 0 * /dev/md_d0 -> d0 + * /dev/md_foo -> foo * /dev/md/1 -> 1 * /dev/md/d1 -> d1 * /dev/md/home -> home @@ -696,9 +697,8 @@ int Create(struct supertype *st, char *mddev, name = strrchr(mddev, '/'); if (name) { name++; - if (strncmp(name, "md_d", 4)==0 && - strlen(name) > 4 && - isdigit(name[4]) && + if (strncmp(name, "md_", 3)==0 && + strlen(name) > 3 && (name-mddev) == 5 /* /dev/ */) name += 3; else if (strncmp(name, "md", 2)==0 && diff --git a/config.c b/config.c index 798338f..189714a 100644 --- a/config.c +++ b/config.c @@ -219,6 +219,7 @@ struct mddev_dev *load_containers(void) struct createinfo createinfo = { .autof = 2, /* by default, create devices with standard names */ .symlinks = 1, + .names = 0, /* By default, stick with numbered md devices. */ #ifdef DEBIAN .gid = 6, /* disk */ .mode = 0660, @@ -334,6 +335,10 @@ static void createline(char *line) createinfo.symlinks = 1; else if (strncasecmp(w, "symlinks=no", 11) == 0) createinfo.symlinks = 0; + else if (strncasecmp(w, "names=yes", 12) == 0) + createinfo.names = 1; + else if (strncasecmp(w, "names=no", 11) == 0) + createinfo.names = 0; else { pr_err("unrecognised word on CREATE line: %s\n", w); diff --git a/mdadm.8.in b/mdadm.8.in index ef93781..740edba 100644 --- a/mdadm.8.in +++ b/mdadm.8.in @@ -2957,19 +2957,33 @@ exists or is listed in the config file. The standard names for non-partitioned arrays (the only sort of md array available in 2.4 and earlier) are of the form .IP -/dev/mdNN +.RB /dev/md NN .PP where NN is a number. The standard names for partitionable arrays (as available from 2.6 -onwards) are of the form +onwards) are of the form: .IP -/dev/md_dNN +.RB /dev/md_d NN .PP -Partition numbers should be indicated by added "pMM" to these, thus "/dev/md/d1p2". +Partition numbers should be indicated by adding "pMM" to these, thus "/dev/md/d1p2". .PP -From kernel version, 2.6.28 the "non-partitioned array" can actually -be partitioned. So the "md_dNN" names are no longer needed, and -partitions such as "/dev/mdNNpXX" are possible. +From kernel version 2.6.28 the "non-partitioned array" can actually +be partitioned. So the "md_d\fBNN\fP" +names are no longer needed, and +partitions such as "/dev/md\fBNN\fPp\fBXX\fp" +are possible. +.PP +From kernel version 2.6.29 standard names can be non-numeric following +the form: +.IP +.RB /dev/md_ XXX +.PP +where +.B XXX +is any string. These names are supported by +.I mdadm +since version 3.3 provided they are enabled in +.IR mdadm.conf . .SH NOTE .I mdadm diff --git a/mdadm.conf.5 b/mdadm.conf.5 index 4ff0a24..1f01648 100644 --- a/mdadm.conf.5 +++ b/mdadm.conf.5 @@ -148,7 +148,7 @@ created as /dev/mdX, then the minor number X is stored. The value is a comma separated list of device names or device name patterns. Only devices with names which match one entry in the list will be used -to assemble the array. Note that the devices +to assemble the array. Note that the devices listed there must also be listed on a DEVICE line. .TP .B level= @@ -339,6 +339,32 @@ or Give .B symlinks=no to suppress this symlink creation. + +.TP +.B names=yes +Since Linux 2.6.29 it has been possible to create +.B md +devices with a name like +.B md_home +rather than just a number, like +.BR md3 . +.I mdadm +will use the numeric alternative by default as other tools that interact +with md arrays may expect only numbers. +If +.B names=yes +is given in +.I mdadm.conf +then +.I mdadm +will use a name when appropriate. +If +.B names=no +is given, then non-numeric +.I md +device names will not be used even if the default changes in a future +release of +.IR mdadm . .RE .TP @@ -437,7 +463,7 @@ The known metadata types are .TP .B POLICY -This is used to specify what automatic behavior is allowed on devices +This is used to specify what automatic behavior is allowed on devices newly appearing in the system and provides a way of marking spares that can be moved to other arrays as well as the migration domains. .I Domain @@ -475,7 +501,7 @@ file glob matching anything from .B /dev/disk/by-path .TP .B type= -either +either .B disk or .BR part . diff --git a/mdadm.h b/mdadm.h index c7b5183..3139259 100644 --- a/mdadm.h +++ b/mdadm.h @@ -257,6 +257,7 @@ struct createinfo { int autof; int mode; int symlinks; + int names; struct supertype *supertype; }; diff --git a/mdopen.c b/mdopen.c index 856b5c0..fc11884 100644 --- a/mdopen.c +++ b/mdopen.c @@ -126,7 +126,7 @@ void make_parts(char *dev, int cnt) * * If udev is configured, we create a temporary device, open it, and * unlink it. - * If not, we create the /dev/mdXX device, and is name is usable, + * If not, we create the /dev/mdXX device, and if name is usable, * /dev/md/name * In any case we return /dev/md/name or (if that isn't available) * /dev/mdXX in 'chosen'. @@ -260,25 +260,6 @@ int create_mddev(char *dev, char *name, int autof, int trustworthy, } } - if (num < 0) { - /* need to choose a free number. */ - char *_devnm = find_free_devnm(use_mdp); - if (devnm == NULL) { - pr_err("No avail md devices - aborting\n"); - return -1; - } - strcpy(devnm, _devnm); - } else { - sprintf(devnm, "%s%d", use_mdp?"md_d":"md", num); - if (mddev_busy(devnm)) { - pr_err("%s is already in use.\n", - dev); - return -1; - } - } - - sprintf(devname, "/dev/%s", devnm); - if (cname[0] == 0 && name) { /* Need to find a name if we can * We don't completely trust 'name'. Truncate to @@ -323,6 +304,40 @@ int create_mddev(char *dev, char *name, int autof, int trustworthy, } } + devnm[0] = 0; + if (num < 0 && cname && ci->names) { + int fd; + int n = -1; + sprintf(devnm, "md_%s", cname); + fd = open("/sys/module/md_mod/parameters/new_array", O_WRONLY); + if (fd >= 0) { + n = write(fd, devnm, strlen(devnm)); + close(fd); + } + if (n < 0) + devnm[0] = 0; + } + if (devnm[0]) + ; + else if (num < 0) { + /* need to choose a free number. */ + char *_devnm = find_free_devnm(use_mdp); + if (devnm == NULL) { + pr_err("No avail md devices - aborting\n"); + return -1; + } + strcpy(devnm, _devnm); + } else { + sprintf(devnm, "%s%d", use_mdp?"md_d":"md", num); + if (mddev_busy(devnm)) { + pr_err("%s is already in use.\n", + dev); + return -1; + } + } + + sprintf(devname, "/dev/%s", devnm); + if (dev && dev[0] == '/') strcpy(chosen, dev); else if (cname[0] == 0)