From b11fe74db0d764c3a245d95bc3651be9bbd59463 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 3 Dec 2013 14:01:24 +1100 Subject: [PATCH] Incremental: improve support for "DEVICE" based restriction in mdadm.conf --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 --- Incremental.c | 18 ++++++++++++++++-- mdadm.8.in | 12 ++++++++++-- mdadm.c | 16 ++++++++-------- mdadm.h | 2 +- udev-md-raid-assembly.rules | 2 +- 5 files changed, 36 insertions(+), 14 deletions(-) diff --git a/Incremental.c b/Incremental.c index 0703deae..f548bad9 100644 --- a/Incremental.c +++ b/Incremental.c @@ -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); diff --git a/mdadm.8.in b/mdadm.8.in index f49822ec..edbedc40 100644 --- a/mdadm.8.in +++ b/mdadm.8.in @@ -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 359e9f91..f6f5b53a 100644 --- 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 c38fdfb9..69facaf3 100644 --- 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); diff --git a/udev-md-raid-assembly.rules b/udev-md-raid-assembly.rules index 72bbed4d..a668e161 100644 --- a/udev-md-raid-assembly.rules +++ b/udev-md-raid-assembly.rules @@ -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" -- 2.39.2