]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Incremental: improve support for "DEVICE" based restriction in mdadm.conf
authorNeilBrown <neilb@suse.de>
Tue, 3 Dec 2013 03:01:24 +0000 (14:01 +1100)
committerNeilBrown <neilb@suse.de>
Tue, 3 Dec 2013 03:01:24 +0000 (14:01 +1100)
--incremental currently fails if the device name passed does not
textually match the names permitted by the DEVICE line in mdadm.conf.
This is problematic when "mdadm -I" is run by udev as the name given
can be a temp name.

This patch makes two improvements:
1/ We generate a list of all existing devices that match the names
  in mdadm.conf, and allow rdev based matching
2/ We allows extra aliases to be provided on the command line, and
  perform textual matching on those.  This is particularly suitable
  for udev usages as ${DEVLINKS} can be provided even though the links
  make not yet be created.

Signed-off-by: NeilBrown <neilb@suse.de>
Incremental.c
mdadm.8.in
mdadm.c
mdadm.h
udev-md-raid-assembly.rules

index 0703deae187811c9e903b0cf50e141d6855dc9c1..f548bad9785dbfe5e78ad67cc047ba16750db136 100644 (file)
@@ -46,7 +46,7 @@ static int try_spare(char *devname, int *dfdp, struct dev_policy *pol,
 static int Incremental_container(struct supertype *st, char *devname,
                                 struct context *c, char *only);
 
-int Incremental(char *devname, struct context *c,
+int Incremental(struct mddev_dev *devlist, struct context *c,
                struct supertype *st)
 {
        /* Add this device to an array, creating the array if necessary
@@ -103,6 +103,7 @@ int Incremental(char *devname, struct context *c,
        struct dev_policy *policy = NULL;
        struct map_ent target_array;
        int have_target;
+       char *devname = devlist->devname;
 
        struct createinfo *ci = conf_get_create_info();
 
@@ -153,7 +154,20 @@ int Incremental(char *devname, struct context *c,
 
        /* 1/ Check if device is permitted by mdadm.conf */
 
-       if (!conf_test_dev(devname)) {
+       for (;devlist; devlist = devlist->next)
+               if (conf_test_dev(devlist->devname))
+                       break;
+       if (!devlist) {
+               devlist = conf_get_devs();
+               for (;devlist; devlist = devlist->next) {
+                       struct stat st2;
+                       if (stat(devlist->devname, &st2) == 0 &&
+                           (st2.st_mode & S_IFMT) == S_IFBLK &&
+                           st2.st_rdev == stb.st_rdev)
+                               break;
+               }
+       }
+       if (!devlist) {
                if (c->verbose >= 0)
                        pr_err("%s not permitted by mdadm.conf.\n",
                               devname);
index f49822eccfaebf77a58dc50b5da8d4f330fc03ff..edbedc40d51382f78eaaf5b683ad15f6b251f429 100644 (file)
@@ -2676,6 +2676,7 @@ Usage:
 .RB [ \-\-run ]
 .RB [ \-\-quiet ]
 .I component-device
+.RI [ optional-aliases-for-device ]
 .HP 12
 Usage:
 .B mdadm \-\-incremental \-\-fail
@@ -2730,16 +2731,23 @@ That is, is it listed in a
 .B DEVICES
 line in that file.  If
 .B DEVICES
-is absent then the default it to allow any device.  Similar if
+is absent then the default it to allow any device.  Similarly if
 .B DEVICES
 contains the special word
 .B partitions
 then any device is allowed.  Otherwise the device name given to
-.I mdadm
+.IR mdadm ,
+or one of the aliases given, or an alias found in the filesystem,
 must match one of the names or patterns in a
 .B DEVICES
 line.
 
+This is the only context where the aliases are used.  They are
+usually provided by a
+.I udev
+rules mentioning
+.BR ${DEVLINKS} .
+
 .IP +
 Does the device have a valid md superblock?  If a specific metadata
 version is requested with
diff --git a/mdadm.c b/mdadm.c
index 359e9f914aa22e762cf035913ce6738c7d498671..f6f5b53af5279134908e0e962c75cf7f6cf1bae2 100644 (file)
--- a/mdadm.c
+++ b/mdadm.c
@@ -1553,16 +1553,16 @@ int main(int argc, char *argv[])
                        }
                        break;
                }
-               if (devlist->next) {
-                       pr_err("--incremental can only handle one device.\n");
-                       rv = 1;
-                       break;
-               }
-               if (devmode == 'f')
+               if (devmode == 'f') {
+                       if (devlist->next) {
+                               pr_err("'--incremental --fail' can only handle one device.\n");
+                               rv = 1;
+                               break;
+                       }
                        rv = IncrementalRemove(devlist->devname, remove_path,
                                               c.verbose);
-               else
-                       rv = Incremental(devlist->devname, &c, ss);
+               else
+                       rv = Incremental(devlist, &c, ss);
                break;
        case AUTODETECT:
                autodetect();
diff --git a/mdadm.h b/mdadm.h
index c38fdfb935735ab12c4f21d61131b1e272f622b1..69facaf329560690bc907311e9de54033f139555 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -1235,7 +1235,7 @@ extern int Update_subarray(char *dev, char *subarray, char *update, struct mddev
 extern int Wait(char *dev);
 extern int WaitClean(char *dev, int sock, int verbose);
 
-extern int Incremental(char *devname, struct context *c,
+extern int Incremental(struct mddev_dev *devlist, struct context *c,
                       struct supertype *st);
 extern void RebuildMap(void);
 extern int IncrementalScan(struct context *c, char *devnm);
index 72bbed4d599c49d80cb79b8cfa139ac46cae092c..a668e161f26fed346a7f46884d33b7b633b910ee 100644 (file)
@@ -12,7 +12,7 @@ LABEL="md_inc"
 
 # remember you can limit what gets auto/incrementally assembled by
 # mdadm.conf(5)'s 'AUTO' and selectively whitelist using 'ARRAY'
-ACTION=="add", IMPORT{program}="/sbin/mdadm --incremental --export $devnode --offroot"
+ACTION=="add", IMPORT{program}="/sbin/mdadm --incremental --export $devnode --offroot ${DEVLINKS}"
 ACTION=="add", ENV{MD_STARTED}=="*unsafe*", ENV{MD_FOREIGN}=="no", ENV{SYSTEMD_WANTS}+="mdadm-last-resort@$env{MD_DEVICE}.timer"
 ACTION=="remove", ENV{ID_PATH}=="?*", RUN+="/sbin/mdadm -If $name --path $env{ID_PATH}"
 ACTION=="remove", ENV{ID_PATH}!="?*", RUN+="/sbin/mdadm -If $name"