diff --git a/Incremental-add-export-handling.patch b/Incremental-add-export-handling.patch new file mode 100644 index 0000000..d16fadc --- /dev/null +++ b/Incremental-add-export-handling.patch @@ -0,0 +1,294 @@ +From 9ca39acb3e8bc31811e463d19fae81c5501aea65 Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Thu, 28 Nov 2013 15:15:30 +1100 +Subject: [PATCH] Incremental: add --export handling. + +If --export is given with --incremental, then + MD_DEVNAME +is output which gives the name of the device (in /dev/md) that +is the array (or container) that the device would be added to. +Also + MD_STARTED +is set to one of + no + unsafe + yes + nothing + +to indicate if the array was started. IF MD_STARTED=unsafe +then it may be appropriate to run + mdadm -R /dev/md/$MD_DEVNAME +after a timeout to ensure newly degraded array are started. + +If + MD_FOREIGN=yes +it might be appropriate to suppress this as the array is +probably not critical. + +Signed-off-by: NeilBrown +--- + Assemble.c | 19 ++++++++++++----- + Incremental.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- + mdadm.8.in | 21 +++++++++++++++++-- + mdadm.h | 6 ++++- + 4 files changed, 94 insertions(+), 16 deletions(-) + +--- mdadm-3.3.orig/Assemble.c ++++ mdadm-3.3/Assemble.c +@@ -1419,7 +1419,7 @@ try_again: + /* This is a member of a container. Try starting the array. */ + int err; + err = assemble_container_content(st, mdfd, content, c, +- chosen_name); ++ chosen_name, NULL); + close(mdfd); + return err; + } +@@ -1771,7 +1771,7 @@ try_again: + #ifndef MDASSEMBLE + int assemble_container_content(struct supertype *st, int mdfd, + struct mdinfo *content, struct context *c, +- char *chosen_name) ++ char *chosen_name, int *result) + { + struct mdinfo *dev, *sra; + int working = 0, preexist = 0; +@@ -1838,7 +1838,9 @@ int assemble_container_content(struct su + + if (enough(content->array.level, content->array.raid_disks, + content->array.layout, content->array.state & 1, avail) == 0) { +- if (c->verbose >= 0) { ++ if (c->export && result) ++ *result |= INCR_NO; ++ else if (c->verbose >= 0) { + pr_err("%s assembled with %d device%s", + chosen_name, preexist + working, + preexist + working == 1 ? "":"s"); +@@ -1854,7 +1856,9 @@ int assemble_container_content(struct su + if (c->runstop <= 0 && + (working + preexist + expansion) < + content->array.working_disks) { +- if (c->verbose >= 0) { ++ if (c->export && result) ++ *result |= INCR_UNSAFE; ++ else if (c->verbose >= 0) { + pr_err("%s assembled with %d device%s", + chosen_name, preexist + working, + preexist + working == 1 ? "":"s"); +@@ -1918,7 +1922,12 @@ int assemble_container_content(struct su + !start_reshape) + block_subarray(content); + +- if (c->verbose >= 0) { ++ if (c->export && result) { ++ if (err) ++ *result |= INCR_NO; ++ else ++ *result |= INCR_YES; ++ } else if (c->verbose >= 0) { + if (err) + pr_err("array %s now has %d device%s", + chosen_name, working + preexist, +--- mdadm-3.3.orig/Incremental.c ++++ mdadm-3.3/Incremental.c +@@ -91,6 +91,7 @@ int Incremental(char *devname, struct co + struct mdinfo *sra = NULL, *d; + struct mddev_ident *match; + char chosen_name[1024]; ++ char *md_devname; + int rv = 1; + struct map_ent *mp, *map = NULL; + int dfd = -1, mdfd = -1; +@@ -138,6 +139,8 @@ int Incremental(char *devname, struct co + if (map_lock(&map)) + pr_err("failed to get " + "exclusive lock on mapfile\n"); ++ if (c->export) ++ printf("MD_DEVNAME=%s\n", devname); + rv = Incremental_container(st, devname, c, NULL); + map_unlock(&map); + return rv; +@@ -459,6 +462,15 @@ int Incremental(char *devname, struct co + info.array.working_disks ++; + + } ++ if (strncmp(chosen_name, "/dev/md/", 8) == 0) ++ md_devname = chosen_name+8; ++ else ++ md_devname = chosen_name; ++ if (c->export) { ++ printf("MD_DEVICE=%s\n", fd2devnm(mdfd)); ++ printf("MD_DEVNAME=%s\n", md_devname); ++ printf("MD_FOREIGN=%s\n", trustworthy == FOREIGN ? "yes" : "no"); ++ } + + /* 7/ Is there enough devices to possibly start the array? */ + /* 7a/ if not, finish with success. */ +@@ -466,7 +478,7 @@ int Incremental(char *devname, struct co + char devnm[32]; + /* Try to assemble within the container */ + sysfs_uevent(sra, "change"); +- if (c->verbose >= 0) ++ if (!c->export && c->verbose >= 0) + pr_err("container %s now has %d device%s\n", + chosen_name, info.array.working_disks, + info.array.working_disks == 1?"":"s"); +@@ -503,7 +515,9 @@ int Incremental(char *devname, struct co + if (enough(info.array.level, info.array.raid_disks, + info.array.layout, info.array.state & 1, + avail) == 0) { +- if (c->verbose >= 0) ++ if (c->export) { ++ printf("MD_STARTED=no\n"); ++ } else if (c->verbose >= 0) + pr_err("%s attached to %s, not enough to start (%d).\n", + devname, chosen_name, active_disks); + rv = 0; +@@ -517,7 +531,9 @@ int Incremental(char *devname, struct co + /* + start the array (auto-readonly). */ + + if (ioctl(mdfd, GET_ARRAY_INFO, &ainf) == 0) { +- if (c->verbose >= 0) ++ if (c->export) { ++ printf("MD_STARTED=already\n"); ++ } else if (c->verbose >= 0) + pr_err("%s attached to %s which is already active.\n", + devname, chosen_name); + rv = 0; +@@ -564,7 +580,9 @@ int Incremental(char *devname, struct co + rv = sysfs_set_str(sra, NULL, + "array_state", "read-auto"); + if (rv == 0) { +- if (c->verbose >= 0) ++ if (c->export) { ++ printf("MD_STARTED=yes\n"); ++ } else if (c->verbose >= 0) + pr_err("%s attached to %s, which has been started.\n", + devname, chosen_name); + rv = 0; +@@ -587,7 +605,9 @@ int Incremental(char *devname, struct co + rv = 1; + } + } else { +- if (c->verbose >= 0) ++ if (c->export) { ++ printf("MD_STARTED=unsafe\n"); ++ } else if (c->verbose >= 0) + pr_err("%s attached to %s, not enough to start safely.\n", + devname, chosen_name); + rv = 0; +@@ -1441,6 +1461,7 @@ static int Incremental_container(struct + int sfd; + int ra_blocked = 0; + int ra_all = 0; ++ int result = 0; + + st->ss->getinfo_super(st, &info, NULL); + +@@ -1448,7 +1469,9 @@ static int Incremental_container(struct + info.container_enough > 0) + /* pass */; + else { +- if (c->verbose) ++ if (c->export) { ++ printf("MD_STARTED=no\n"); ++ } else if (c->verbose) + pr_err("not enough devices to start the container\n"); + return 0; + } +@@ -1469,8 +1492,12 @@ static int Incremental_container(struct + + list = st->ss->container_content(st, NULL); + /* when nothing to activate - quit */ +- if (list == NULL) ++ if (list == NULL) { ++ if (c->export) { ++ printf("MD_STARTED=nothing\n"); ++ } + return 0; ++ } + for (ra = list ; ra ; ra = ra->next) { + int mdfd; + char chosen_name[1024]; +@@ -1560,9 +1587,30 @@ static int Incremental_container(struct + } + + assemble_container_content(st, mdfd, ra, c, +- chosen_name); ++ chosen_name, &result); + close(mdfd); + } ++ if (c->export && result) { ++ char sep = '='; ++ printf("MD_STARTED"); ++ if (result & INCR_NO) { ++ printf("%cno", sep); ++ sep = ','; ++ } ++ if (result & INCR_UNSAFE) { ++ printf("%cunsafe", sep); ++ sep = ','; ++ } ++ if (result & INCR_ALREADY) { ++ printf("%calready", sep); ++ sep = ','; ++ } ++ if (result & INCR_YES) { ++ printf("%cyes", sep); ++ sep = ','; ++ } ++ printf("\n"); ++ } + + /* don't move spares to container with volume being activated + when all volumes are blocked */ +--- mdadm-3.3.orig/mdadm.8.in ++++ mdadm-3.3/mdadm.8.in +@@ -1428,13 +1428,30 @@ absolute filepath or a link, e.g. + .TP + .BR \-Y ", " \-\-export + When used with +-.B \-\-detail , \-\-detail-platform +-or ++.BR \-\-detail , ++.BR \-\-detail-platform , + .BR \-\-examine , ++or ++.B \-\-incremental + output will be formatted as + .B key=value + pairs for easy import into the environment. + ++With ++.B \-\-incremental ++The value ++.B MD_STARTED ++indicates whether an array was started ++.RB ( yes ) ++or not, which may include a reason ++.RB ( unsafe ", " nothing ", " no ). ++Also the value ++.B MD_FOREIGN ++indicates if the array is expected on this host ++.RB ( no ), ++or seems to be from elsewhere ++.RB ( yes ). ++ + .TP + .BR \-E ", " \-\-examine + Print contents of the metadata stored on the named device(s). +--- mdadm-3.3.orig/mdadm.h ++++ mdadm-3.3/mdadm.h +@@ -1328,7 +1328,11 @@ extern void append_metadata_update(struc + extern int assemble_container_content(struct supertype *st, int mdfd, + struct mdinfo *content, + struct context *c, +- char *chosen_name); ++ char *chosen_name, int *result); ++#define INCR_NO 1 ++#define INCR_UNSAFE 2 ++#define INCR_ALREADY 4 ++#define INCR_YES 8 + extern struct mdinfo *container_choose_spares(struct supertype *st, + unsigned long long min_size, + struct domainlist *domlist, diff --git a/Incremental-improve-support-for-DEVICE-based-restric.patch b/Incremental-improve-support-for-DEVICE-based-restric.patch new file mode 100644 index 0000000..763b60f --- /dev/null +++ b/Incremental-improve-support-for-DEVICE-based-restric.patch @@ -0,0 +1,154 @@ +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(-) + +--- mdadm-3.3.orig/Incremental.c ++++ mdadm-3.3/Incremental.c +@@ -46,7 +46,7 @@ static int try_spare(char *devname, int + 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 co + 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 co + + /* 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); +--- mdadm-3.3.orig/mdadm.8.in ++++ mdadm-3.3/mdadm.8.in +@@ -2664,6 +2664,7 @@ Usage: + .RB [ \-\-run ] + .RB [ \-\-quiet ] + .I component-device ++.RI [ optional-aliases-for-device ] + .HP 12 + Usage: + .B mdadm \-\-incremental \-\-fail +@@ -2718,16 +2719,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 +--- mdadm-3.3.orig/mdadm.c ++++ mdadm-3.3/mdadm.c +@@ -1544,16 +1544,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(); +--- mdadm-3.3.orig/mdadm.h ++++ mdadm-3.3/mdadm.h +@@ -1232,7 +1232,7 @@ extern int Update_subarray(char *dev, ch + 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); +--- mdadm-3.3.orig/udev-md-raid-assembly.rules ++++ mdadm-3.3/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" diff --git a/Restructure-assemble_container_content-and-improve-m.patch b/Restructure-assemble_container_content-and-improve-m.patch new file mode 100644 index 0000000..3011bd4 --- /dev/null +++ b/Restructure-assemble_container_content-and-improve-m.patch @@ -0,0 +1,237 @@ +From c1736844ba49ec1a8731b5815abfd6530b982a3b Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Thu, 28 Nov 2013 14:47:41 +1100 +Subject: [PATCH 1/2] Restructure assemble_container_content and improve + messages. + +We lose one level of indent, and now get told the difference between +'not assemble because not safe' and 'not assembled because not enough +devices'. + +Signed-off-by: NeilBrown +--- + Assemble.c | 176 ++++++++++++++++++++++++++++++++++--------------------------- + 1 file changed, 99 insertions(+), 77 deletions(-) + +diff --git a/Assemble.c b/Assemble.c +index 4d5ceeac8674..11b77c288608 100644 +--- a/Assemble.c ++++ b/Assemble.c +@@ -1779,6 +1779,8 @@ int assemble_container_content(struct supertype *st, int mdfd, + struct map_ent *map = NULL; + int old_raid_disks; + int start_reshape; ++ char *avail = NULL; ++ int err; + + sysfs_init(content, mdfd, NULL); + +@@ -1812,7 +1814,10 @@ int assemble_container_content(struct supertype *st, int mdfd, + if (sra) + sysfs_free(sra); + old_raid_disks = content->array.raid_disks - content->delta_disks; +- for (dev = content->devs; dev; dev = dev->next) ++ avail = xcalloc(content->array.raid_disks, 1); ++ for (dev = content->devs; dev; dev = dev->next) { ++ if (dev->disk.raid_disk >= 0) ++ avail[dev->disk.raid_disk] = 1; + if (sysfs_add_disk(content, dev, 1) == 0) { + if (dev->disk.raid_disk >= old_raid_disks && + content->reshape_active) +@@ -1821,100 +1826,117 @@ int assemble_container_content(struct supertype *st, int mdfd, + working++; + } else if (errno == EEXIST) + preexist++; +- if (working + expansion == 0 && c->runstop <= 0) ++ } ++ if (working + expansion == 0 && c->runstop <= 0) { ++ free(avail); + return 1;/* Nothing new, don't try to start */ +- ++ } + map_update(&map, fd2devnm(mdfd), + content->text_version, + content->uuid, chosen_name); + +- if (c->runstop > 0 || +- (working + preexist + expansion) >= +- content->array.working_disks) { +- int err; +- +- if (start_reshape) { +- int spare = content->array.raid_disks + expansion; +- if (restore_backup(st, content, +- working, +- spare, c->backup_file, c->verbose) == 1) +- return 1; +- +- err = sysfs_set_str(content, NULL, +- "array_state", "readonly"); +- if (err) +- return 1; +- +- if (st->ss->external) { +- if (!mdmon_running(st->container_devnm)) +- start_mdmon(st->container_devnm); +- ping_monitor(st->container_devnm); +- if (mdmon_running(st->container_devnm) && +- st->update_tail == NULL) +- st->update_tail = &st->updates; +- } +- +- err = Grow_continue(mdfd, st, content, c->backup_file, +- c->freeze_reshape); +- } else switch(content->array.level) { +- case LEVEL_LINEAR: +- case LEVEL_MULTIPATH: +- case 0: +- err = sysfs_set_str(content, NULL, "array_state", +- c->readonly ? "readonly" : "active"); +- break; +- default: +- err = sysfs_set_str(content, NULL, "array_state", +- "readonly"); +- /* start mdmon if needed. */ +- if (!err) { +- if (!mdmon_running(st->container_devnm)) +- start_mdmon(st->container_devnm); +- ping_monitor(st->container_devnm); +- } +- break; +- } +- if (!err) +- sysfs_set_safemode(content, content->safe_mode_delay); +- +- /* Block subarray here if it is not reshaped now +- * It has be blocked a little later to allow mdmon to switch in +- * in to R/W state +- */ +- if (st->ss->external && content->recovery_blocked && +- !start_reshape) +- block_subarray(content); + ++ if (enough(content->array.level, content->array.raid_disks, ++ content->array.layout, content->array.state & 1, avail) == 0) { + if (c->verbose >= 0) { +- if (err) +- pr_err("array %s now has %d device%s", +- chosen_name, working + preexist, +- working + preexist == 1 ? "":"s"); +- else +- pr_err("Started %s with %d device%s", +- chosen_name, working + preexist, +- working + preexist == 1 ? "":"s"); ++ pr_err("%s assembled with %d device%s", ++ chosen_name, preexist + working, ++ preexist + working == 1 ? "":"s"); + if (preexist) + fprintf(stderr, " (%d new)", working); +- if (expansion) +- fprintf(stderr, " ( + %d for expansion)", +- expansion); +- fprintf(stderr, "\n"); ++ fprintf(stderr, " but not started\n"); + } +- if (!err) +- wait_for(chosen_name, mdfd); +- return err; +- /* FIXME should have an O_EXCL and wait for read-auto */ +- } else { ++ free(avail); ++ return 1; ++ } ++ free(avail); ++ ++ if (c->runstop <= 0 && ++ (working + preexist + expansion) < ++ content->array.working_disks) { + if (c->verbose >= 0) { + pr_err("%s assembled with %d device%s", + chosen_name, preexist + working, + preexist + working == 1 ? "":"s"); + if (preexist) + fprintf(stderr, " (%d new)", working); +- fprintf(stderr, " but not started\n"); ++ fprintf(stderr, " but not safe to start\n"); + } + return 1; + } ++ ++ ++ if (start_reshape) { ++ int spare = content->array.raid_disks + expansion; ++ if (restore_backup(st, content, ++ working, ++ spare, c->backup_file, c->verbose) == 1) ++ return 1; ++ ++ err = sysfs_set_str(content, NULL, ++ "array_state", "readonly"); ++ if (err) ++ return 1; ++ ++ if (st->ss->external) { ++ if (!mdmon_running(st->container_devnm)) ++ start_mdmon(st->container_devnm); ++ ping_monitor(st->container_devnm); ++ if (mdmon_running(st->container_devnm) && ++ st->update_tail == NULL) ++ st->update_tail = &st->updates; ++ } ++ ++ err = Grow_continue(mdfd, st, content, c->backup_file, ++ c->freeze_reshape); ++ } else switch(content->array.level) { ++ case LEVEL_LINEAR: ++ case LEVEL_MULTIPATH: ++ case 0: ++ err = sysfs_set_str(content, NULL, "array_state", ++ c->readonly ? "readonly" : "active"); ++ break; ++ default: ++ err = sysfs_set_str(content, NULL, "array_state", ++ "readonly"); ++ /* start mdmon if needed. */ ++ if (!err) { ++ if (!mdmon_running(st->container_devnm)) ++ start_mdmon(st->container_devnm); ++ ping_monitor(st->container_devnm); ++ } ++ break; ++ } ++ if (!err) ++ sysfs_set_safemode(content, content->safe_mode_delay); ++ ++ /* Block subarray here if it is not reshaped now ++ * It has be blocked a little later to allow mdmon to switch in ++ * in to R/W state ++ */ ++ if (st->ss->external && content->recovery_blocked && ++ !start_reshape) ++ block_subarray(content); ++ ++ if (c->verbose >= 0) { ++ if (err) ++ pr_err("array %s now has %d device%s", ++ chosen_name, working + preexist, ++ working + preexist == 1 ? "":"s"); ++ else ++ pr_err("Started %s with %d device%s", ++ chosen_name, working + preexist, ++ working + preexist == 1 ? "":"s"); ++ if (preexist) ++ fprintf(stderr, " (%d new)", working); ++ if (expansion) ++ fprintf(stderr, " ( + %d for expansion)", ++ expansion); ++ fprintf(stderr, "\n"); ++ } ++ if (!err) ++ wait_for(chosen_name, mdfd); ++ return err; ++ /* FIXME should have an O_EXCL and wait for read-auto */ + } + #endif +-- +1.8.3.1.487.g3e7a5b4 + diff --git a/mdadm.changes b/mdadm.changes index 9e913d5..9f488a1 100644 --- a/mdadm.changes +++ b/mdadm.changes @@ -1,3 +1,17 @@ +------------------------------------------------------------------- +Tue Dec 3 03:06:07 UTC 2013 - nfbrown@suse.com + +- Restructure-assemble_container_content-and-improve-m.patch +- Incremental-add-export-handling.patch +- udev-rules.degraded +- systemd-mdadm-last-resort@.service +- systemd-mdadm-last-resort@.timer + Teach systemd to start degraded arrays after a timeout if + some missing devices never appear (bnc#832501) +- Incremental-improve-support-for-DEVICE-based-restric.patch + Teach "mdadm --incremental" to handle "DEVICE" lists from + mdadm.conf properly (bnc@851993) + ------------------------------------------------------------------- Mon Nov 11 00:45:03 UTC 2013 - nfbrown@suse.com diff --git a/mdadm.spec b/mdadm.spec index 802f7d0..69ed575 100644 --- a/mdadm.spec +++ b/mdadm.spec @@ -43,6 +43,8 @@ Source5: mkinitrd-setup.sh Source6: mkinitrd-boot.sh Source7: mdadm.cron Source8: mdadm.shutdown +Source9: systemd-mdadm-last-resort@.timer +Source10: systemd-mdadm-last-resort@.service # PATCH-FIX-UPSTREAM config-set-auto_seen-after-processing-the-auto-line.patch upstream-bugfix nfbrown@suse.de Patch1: config-set-auto_seen-after-processing-the-auto-line.patch # PATCH-FIX-UPSTREAM DDF-allow-for-possibility-that-there-is-no-secondary.patch upstream-bugfix nfbrown@suse.de @@ -67,6 +69,14 @@ Patch10: DDF-add_to_super_ddf-be-careful-with-workspace_lba.patch Patch11: Monitor-write-meta-data-in-readonly-state-sometimes.patch # PATCH-FIX-UPSTREAM Assembe-fix-bug-in-force_array-it-wasn-t-forcing-pro.patch upstream-bugfix nfbrown@suse.de Patch12: Assembe-fix-bug-in-force_array-it-wasn-t-forcing-pro.patch +# PATCH-FEATURE-UPSTREAM Restructure-assemble_container_content-and-improve-m.patch bnc#832501 nfbrown@suse.de +Patch13: Restructure-assemble_container_content-and-improve-m.patch +# PATCH-FEATURE-UPSTREAM Incremental-add-export-handling.patch bnc#832501 nfbrown@suse.de +Patch14: Incremental-add-export-handling.patch +# PATCH-FEATURE-UPSTREAM udev-rules.degraded bnc#832501 nfbrown@suse.de +Patch15: udev-rules.degraded +# PATCH-FEATURE-UPSTREAM Incremental-improve-support-for-DEVICE-based-restric.patch bnc#851993 nfbrown@suse.de +Patch16: Incremental-improve-support-for-DEVICE-based-restric.patch %define _udevdir %(pkg-config --variable=udevdir udev) %define _systemdshutdowndir %{_unitdir}/../system-shutdown @@ -90,6 +100,10 @@ programs but with a very different interface. %patch10 -p1 %patch11 -p1 %patch12 -p1 +%patch13 -p1 +%patch14 -p1 +%patch15 -p1 +%patch16 -p1 %build make %{?_smp_mflags} CC="%__cc" CXFLAGS="$RPM_OPT_FLAGS -Wno-error" @@ -112,6 +126,8 @@ install -m 644 %{S:2} %{buildroot}%{_var}/adm/fillup-templates/ ln -sf ../../etc/init.d/mdadmd %{buildroot}/%{_sbindir}/rcmdadmd install -d %{buildroot}%{_systemdshutdowndir} install -m 755 %{S:8} %{buildroot}%{_systemdshutdowndir}/mdadm.shutdown +install -m 644 %{S:9} %{buildroot}%{_unitdir}/mdadm-last-resort@.timer +install -m 644 %{S:10} %{buildroot}%{_unitdir}/mdadm-last-resort@.service %post [ -x /sbin/mkinitrd_setup ] && mkinitrd_setup @@ -162,5 +178,7 @@ rm -rf %{buildroot} /etc/cron.daily/mdadm %{_systemdshutdowndir}/mdadm.shutdown %{_unitdir}/mdmon@.service +%{_unitdir}/mdadm-last-resort@.timer +%{_unitdir}/mdadm-last-resort@.service %changelog diff --git a/systemd-mdadm-last-resort@.service b/systemd-mdadm-last-resort@.service new file mode 100644 index 0000000..5a7108d --- /dev/null +++ b/systemd-mdadm-last-resort@.service @@ -0,0 +1,7 @@ +[Unit] +Description=Activate md array even though degraded +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/sbin/mdadm --run /dev/%i diff --git a/systemd-mdadm-last-resort@.timer b/systemd-mdadm-last-resort@.timer new file mode 100644 index 0000000..8354dad --- /dev/null +++ b/systemd-mdadm-last-resort@.timer @@ -0,0 +1,6 @@ +[Unit] +Description=Timer to wait for more drives before activating degraded array. +DefaultDependencies=no + +[Timer] +OnActiveSec=30 diff --git a/udev-rules.degraded b/udev-rules.degraded new file mode 100644 index 0000000..b60a614 --- /dev/null +++ b/udev-rules.degraded @@ -0,0 +1,16 @@ +--- + udev-md-raid-assembly.rules | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- mdadm-3.3.orig/udev-md-raid-assembly.rules ++++ mdadm-3.3/udev-md-raid-assembly.rules +@@ -12,7 +12,8 @@ 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", RUN+="/sbin/mdadm --incremental $devnode --offroot" ++ACTION=="add", IMPORT{program}="/sbin/mdadm --incremental --export $devnode --offroot" ++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" +