Hello community, here is the log from the commit of package mdadm for openSUSE:Factory checked in at 2013-12-06 11:46:05 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/mdadm (Old) and /work/SRC/openSUSE:Factory/.mdadm.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "mdadm" Changes: -------- --- /work/SRC/openSUSE:Factory/mdadm/mdadm.changes 2013-11-12 09:51:54.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.mdadm.new/mdadm.changes 2013-12-06 11:46:06.000000000 +0100 @@ -1,0 +2,24 @@ +Wed Dec 4 23:57:16 UTC 2013 - nfbr...@suse.com + +- Assemble-Incremental-don-t-hold-O_EXCL-on-mddev-afte.patch + Ensure fsck/mount don't find an md array to be BUSY + the moment it appears. +- mkinitrd-setup.sh: Make the array device names in + /etc/mdadm.conf in the initrd match those in /etc/mdadm.conf + in the root filesystem. (bnc#851993) + +------------------------------------------------------------------- +Tue Dec 3 03:06:07 UTC 2013 - nfbr...@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) + +------------------------------------------------------------------- New: ---- Assemble-Incremental-don-t-hold-O_EXCL-on-mddev-afte.patch Incremental-add-export-handling.patch Incremental-improve-support-for-DEVICE-based-restric.patch Restructure-assemble_container_content-and-improve-m.patch systemd-mdadm-last-resort@.service systemd-mdadm-last-resort@.timer udev-rules.degraded ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ mdadm.spec ++++++ --- /var/tmp/diff_new_pack.JTd7H1/_old 2013-12-06 11:46:08.000000000 +0100 +++ /var/tmp/diff_new_pack.JTd7H1/_new 2013-12-06 11:46:08.000000000 +0100 @@ -43,6 +43,8 @@ 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 nfbr...@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 nfbr...@suse.de @@ -67,6 +69,16 @@ 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 nfbr...@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 nfbr...@suse.de +Patch13: Restructure-assemble_container_content-and-improve-m.patch +# PATCH-FEATURE-UPSTREAM Incremental-add-export-handling.patch bnc#832501 nfbr...@suse.de +Patch14: Incremental-add-export-handling.patch +# PATCH-FEATURE-UPSTREAM udev-rules.degraded bnc#832501 nfbr...@suse.de +Patch15: udev-rules.degraded +# PATCH-FEATURE-UPSTREAM Incremental-improve-support-for-DEVICE-based-restric.patch bnc#851993 nfbr...@suse.de +Patch16: Incremental-improve-support-for-DEVICE-based-restric.patch +# PATCH-FIX-UPSTREAM Assemble-Incremental-don-t-hold-O_EXCL-on-mddev-afte.patch nfbr...@suse.de +Patch17: Assemble-Incremental-don-t-hold-O_EXCL-on-mddev-afte.patch %define _udevdir %(pkg-config --variable=udevdir udev) %define _systemdshutdowndir %{_unitdir}/../system-shutdown @@ -90,6 +102,11 @@ %patch10 -p1 %patch11 -p1 %patch12 -p1 +%patch13 -p1 +%patch14 -p1 +%patch15 -p1 +%patch16 -p1 +%patch17 -p1 %build make %{?_smp_mflags} CC="%__cc" CXFLAGS="$RPM_OPT_FLAGS -Wno-error" @@ -112,6 +129,8 @@ 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 +181,7 @@ /etc/cron.daily/mdadm %{_systemdshutdowndir}/mdadm.shutdown %{_unitdir}/mdmon@.service +%{_unitdir}/mdadm-last-resort@.timer +%{_unitdir}/mdadm-last-resort@.service %changelog ++++++ Assemble-Incremental-don-t-hold-O_EXCL-on-mddev-afte.patch ++++++ >From 8832342d3aad09d3c86af6dc9b137d6fd83af1ae Mon Sep 17 00:00:00 2001 From: NeilBrown <ne...@suse.de> Date: Thu, 5 Dec 2013 10:35:16 +1100 Subject: [PATCH] Assemble/Incremental: don't hold O_EXCL on mddev after assembly. As soon as the array is assembled, udev or systemd might run fsck and mount it. So we need to drop O_EXCL promptly. Signed-off-by: NeilBrown <ne...@suse.de> --- Assemble.c | 1 + Incremental.c | 10 +++++++--- mdadm.h | 1 + util.c | 14 ++++++++++++++ 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/Assemble.c b/Assemble.c index 44e905bb8667..7e8e79570352 100644 --- a/Assemble.c +++ b/Assemble.c @@ -1037,6 +1037,7 @@ static int start_array(int mdfd, } else #endif rv = ioctl(mdfd, RUN_ARRAY, NULL); + reopen_mddev(mdfd); /* drop O_EXCL */ if (rv == 0) { if (c->verbose >= 0) { pr_err("%s has been started with %d drive%s", diff --git a/Incremental.c b/Incremental.c index f548bad9785d..c9372587f518 100644 --- a/Incremental.c +++ b/Incremental.c @@ -588,10 +588,14 @@ int Incremental(struct mddev_dev *devlist, struct context *c, else rv = sysfs_set_str(sra, NULL, "array_state", "read-auto"); + /* Array might be O_EXCL which will interfere with + * fsck and mount. So re-open without O_EXCL. + */ + reopen_mddev(mdfd); if (rv == 0) { - if (c->export) { - printf("MD_STARTED=yes\n"); - } else 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; diff --git a/mdadm.h b/mdadm.h index 69facaf32956..7f222a6d7a78 100644 --- a/mdadm.h +++ b/mdadm.h @@ -1272,6 +1272,7 @@ extern int check_partitions(int fd, char *dname, extern int get_mdp_major(void); extern int dev_open(char *dev, int flags); extern int open_dev(char *devnm); +extern void reopen_mddev(int mdfd); extern int open_dev_flags(char *devnm, int flags); extern int open_dev_excl(char *devnm); extern int is_standard(char *dev, int *nump); diff --git a/util.c b/util.c index 12a19e7a5a3a..e32d97a011e7 100644 --- a/util.c +++ b/util.c @@ -1950,3 +1950,17 @@ int in_initrd(void) ((unsigned long)s.f_type == TMPFS_MAGIC || (unsigned long)s.f_type == RAMFS_MAGIC); } + +void reopen_mddev(int mdfd) +{ + /* Re-open without any O_EXCL, but keep + * the same fd + */ + char *devnm; + int fd; + devnm = fd2devnm(mdfd); + close(mdfd); + fd = open_dev(devnm); + if (fd >= 0 && fd != mdfd) + dup2(fd, mdfd); +} -- 1.8.3.1.487.g3e7a5b4 ++++++ Incremental-add-export-handling.patch ++++++ >From 9ca39acb3e8bc31811e463d19fae81c5501aea65 Mon Sep 17 00:00:00 2001 From: NeilBrown <ne...@suse.de> 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 <ne...@suse.de> --- 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, ++++++ Incremental-improve-support-for-DEVICE-based-restric.patch ++++++ >From b11fe74db0d764c3a245d95bc3651be9bbd59463 Mon Sep 17 00:00:00 2001 From: NeilBrown <ne...@suse.de> 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 <ne...@suse.de> --- 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" ++++++ Restructure-assemble_container_content-and-improve-m.patch ++++++ >From c1736844ba49ec1a8731b5815abfd6530b982a3b Mon Sep 17 00:00:00 2001 From: NeilBrown <ne...@suse.de> 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 <ne...@suse.de> --- 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 ++++++ mkinitrd-setup.sh ++++++ --- /var/tmp/diff_new_pack.JTd7H1/_old 2013-12-06 11:46:08.000000000 +0100 +++ /var/tmp/diff_new_pack.JTd7H1/_new 2013-12-06 11:46:08.000000000 +0100 @@ -81,6 +81,15 @@ echo "unrecognized container for $md_dev: $container" ;; esac + # If /etc/mdadm.conf contains a different name for this + # array, then use that. + md_uuid=`echo $mdconf | sed -n -e 's/.* UUID=\([0-9a-f:]*\).*/\1/p'` + if [ -f /etc/mdadm.conf -a -n "$md_uuid" ]; then + md_devname=`sed -n -e 's,^ARRAY */dev/\([^ ]*\) .*[Uu][Uu][Ii][Dd]='$md_uuid'.*,\1,p' /etc/mdadm.conf` + if [ -n "$md_devname" ]; then + mdconf=`echo $mdconf | sed -e 's,^ARRAY /dev/\([^ ]*\),ARRAY /dev/'$md_devname','` + fi + fi md_conf["$md_dev"]="$mdconf" root_md=1 done ++++++ systemd-mdadm-last-resort@.service ++++++ [Unit] Description=Activate md array even though degraded DefaultDependencies=no [Service] Type=oneshot ExecStart=/sbin/mdadm --run /dev/%i ++++++ systemd-mdadm-last-resort@.timer ++++++ [Unit] Description=Timer to wait for more drives before activating degraded array. DefaultDependencies=no [Timer] OnActiveSec=30 ++++++ udev-rules.degraded ++++++ --- 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" -- To unsubscribe, e-mail: opensuse-commit+unsubscr...@opensuse.org For additional commands, e-mail: opensuse-commit+h...@opensuse.org