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 <neilb@suse.de>
This commit is contained in:
NeilBrown 2013-12-03 14:01:24 +11:00
parent 169ffac7ad
commit b11fe74db0
5 changed files with 36 additions and 14 deletions

View 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);

View 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

16
mdadm.c
View File

@ -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();

View File

@ -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);

View 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"