diff --git a/0001-Assemble-allow-load_devices-to-change-the-st-which-i.patch b/0001-Assemble-allow-load_devices-to-change-the-st-which-i.patch new file mode 100644 index 0000000..928d2b9 --- /dev/null +++ b/0001-Assemble-allow-load_devices-to-change-the-st-which-i.patch @@ -0,0 +1,82 @@ +From df842e69a3cb7316a06ba45f8f04d7b9beb0170f Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Tue, 25 Feb 2014 14:54:34 +1100 +Subject: [PATCH 1/3] Assemble: allow load_devices to change the 'st' which is + passed in. + +The given 'st' might not be best. Making this interface change +will allow load_devices to return a better 'st'. + +Signed-off-by: NeilBrown +--- + Assemble.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +--- mdadm-3.3.orig/Assemble.c ++++ mdadm-3.3/Assemble.c +@@ -551,7 +551,7 @@ struct devs { + }; + + static int load_devices(struct devs *devices, char *devmap, +- struct mddev_ident *ident, struct supertype *st, ++ struct mddev_ident *ident, struct supertype **stp, + struct mddev_dev *devlist, struct context *c, + struct mdinfo *content, + int mdfd, char *mddev, +@@ -567,6 +567,7 @@ static int load_devices(struct devs *dev + int most_recent = -1; + int bestcnt = 0; + int *best = *bestp; ++ struct supertype *st = *stp; + + for (tmpdev = devlist; tmpdev; tmpdev=tmpdev->next) { + char *devname = tmpdev->devname; +@@ -610,6 +611,7 @@ static int load_devices(struct devs *dev + close(mdfd); + free(devices); + free(devmap); ++ *stp = st; + return -1; + } + tst->ss->getinfo_super(tst, content, devmap + devcnt * content->array.raid_disks); +@@ -636,6 +638,7 @@ static int load_devices(struct devs *dev + close(dfd); + free(devices); + free(devmap); ++ *stp = st; + return -1; + } + if (strcmp(c->update, "uuid")==0 && +@@ -675,6 +678,7 @@ static int load_devices(struct devs *dev + close(mdfd); + free(devices); + free(devmap); ++ *stp = st; + return -1; + } + tst->ss->getinfo_super(tst, content, devmap + devcnt * content->array.raid_disks); +@@ -759,6 +763,7 @@ static int load_devices(struct devs *dev + close(mdfd); + free(devices); + free(devmap); ++ *stp = st; + return -1; + } + if (best[i] == -1 +@@ -772,6 +777,7 @@ static int load_devices(struct devs *dev + *most_recentp = most_recent; + *bestcntp = bestcnt; + *bestp = best; ++ *stp = st; + return devcnt; + } + +@@ -1432,7 +1438,7 @@ try_again: + /* Ok, no bad inconsistancy, we can try updating etc */ + devices = xcalloc(num_devs, sizeof(*devices)); + devmap = xcalloc(num_devs, content->array.raid_disks); +- devcnt = load_devices(devices, devmap, ident, st, devlist, ++ devcnt = load_devices(devices, devmap, ident, &st, devlist, + c, content, mdfd, mddev, + &most_recent, &bestcnt, &best, inargv); + if (devcnt < 0) diff --git a/0001-DDF-mark-missing-on-assembly-device-properly.patch b/0001-DDF-mark-missing-on-assembly-device-properly.patch new file mode 100644 index 0000000..f2553dc --- /dev/null +++ b/0001-DDF-mark-missing-on-assembly-device-properly.patch @@ -0,0 +1,75 @@ +From e5a03804dc27e662be94290c62760dbc544c0211 Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Tue, 1 Apr 2014 16:15:06 +1100 +Subject: [PATCH 1/4] DDF: mark missing-on-assembly device properly. + +As well as removing from the array we really should mark +it is 'failed', and mark the array as degraded. + +Signed-off-by: NeilBrown +--- + super-ddf.c | 31 ++++++++++++++++++++++++++++--- + 1 file changed, 28 insertions(+), 3 deletions(-) + +--- mdadm-3.3.orig/super-ddf.c ++++ mdadm-3.3/super-ddf.c +@@ -4117,7 +4117,7 @@ static int ddf_open_new(struct supertype + return 0; + } + +-static void handle_missing(struct ddf_super *ddf, int inst) ++static void handle_missing(struct ddf_super *ddf, struct active_array *a, int inst) + { + /* This member array is being activated. If any devices + * are missing they must now be marked as failed. +@@ -4126,7 +4126,9 @@ static void handle_missing(struct ddf_su + unsigned int n_bvd; + struct vcl *vcl; + struct dl *dl; ++ int pd; + int n; ++ int state; + + for (n = 0; ; n++) { + vc = find_vdcr(ddf, inst, n, &n_bvd, &vcl); +@@ -4138,7 +4140,30 @@ static void handle_missing(struct ddf_su + if (dl) + /* Found this disk, so not missing */ + continue; +- vc->phys_refnum[n_bvd] = cpu_to_be32(0); ++ ++ /* Mark the device as failed/missing. */ ++ pd = find_phys(ddf, vc->phys_refnum[n_bvd]); ++ if (pd >= 0 && be16_and(ddf->phys->entries[pd].state, ++ cpu_to_be16(DDF_Online))) { ++ be16_clear(ddf->phys->entries[pd].state, ++ cpu_to_be16(DDF_Online)); ++ be16_set(ddf->phys->entries[pd].state, ++ cpu_to_be16(DDF_Failed|DDF_Missing)); ++ vc->phys_refnum[n_bvd] = cpu_to_be32(0); ++ ddf_set_updates_pending(ddf); ++ } ++ ++ /* Mark the array as Degraded */ ++ state = get_svd_state(ddf, vcl); ++ if (ddf->virt->entries[inst].state != ++ ((ddf->virt->entries[inst].state & ~DDF_state_mask) ++ | state)) { ++ ddf->virt->entries[inst].state = ++ (ddf->virt->entries[inst].state & ~DDF_state_mask) ++ | state; ++ a->check_degraded = 1; ++ ddf_set_updates_pending(ddf); ++ } + } + } + +@@ -4157,7 +4182,7 @@ static int ddf_set_array_state(struct ac + int inst = a->info.container_member; + int old = ddf->virt->entries[inst].state; + if (consistent == 2) { +- handle_missing(ddf, inst); ++ handle_missing(ddf, a, inst); + /* Should check if a recovery should be started FIXME */ + consistent = 1; + if (!is_resync_complete(&a->info)) diff --git a/0001-mdmon-.service-Change-type-of-process-start-up-to-fo.patch b/0001-mdmon-.service-Change-type-of-process-start-up-to-fo.patch new file mode 100644 index 0000000..83cf55e --- /dev/null +++ b/0001-mdmon-.service-Change-type-of-process-start-up-to-fo.patch @@ -0,0 +1,42 @@ +From 2167de78aab599e7a7a8d057ef04bf18527bc129 Mon Sep 17 00:00:00 2001 +From: Pawel Baldysiak +Date: Thu, 6 Mar 2014 15:51:44 +0100 +Subject: [PATCH 1/6] mdmon@.service: Change type of process start-up to + 'forking'. + +Mdadm does not wait enough time when mdmon is started by systemd. +It causes various problems with behaviour of a RAID volume with external metadata. +For example: mdmon does not update a value of checkpoint during migration +and second RAID5 volume is read-only after reboot done during +container reshape (both problems occur with IMSM matadata). +If a type of process start-up is changed to 'forking', systemctl will +wait until mdmon (parent) process exits after calling fork. +This way mdmon will always be fully initialized after start_mdmon +and these problems will not occur. +In this case it is recommended to add a path to PIDFile, so that systemd +does not have to guess a PID of the mdmon process. + +Signed-off-by: Pawel Baldysiak +Reviewed-by: Artur Paszkiewicz +Reviewed-by: Lukasz Dorau +Signed-off-by: NeilBrown +--- + systemd/mdmon@.service | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/systemd/mdmon@.service b/systemd/mdmon@.service +index 5520cd03137c..304b26e890c7 100644 +--- a/systemd/mdmon@.service ++++ b/systemd/mdmon@.service +@@ -14,5 +14,7 @@ Before=initrd-switch-root.target + # mdmon should never complain due to lack of a platform, + # that is mdadm's job if at all. + Environment=IMSM_NO_PLATFORM=1 +-ExecStart=/sbin/mdmon --foreground %I ++ExecStart=/sbin/mdmon %I ++Type=forking ++PIDFile=/run/mdadm/%I.pid + KillMode=none +-- +1.8.3.1.487.g3e7a5b4 + diff --git a/0001-systemd-various-fixes-for-boot-with-container-arrays.patch b/0001-systemd-various-fixes-for-boot-with-container-arrays.patch new file mode 100644 index 0000000..c2d916a --- /dev/null +++ b/0001-systemd-various-fixes-for-boot-with-container-arrays.patch @@ -0,0 +1,83 @@ +From 8d1d32bb33da1bd08a398d26f364b84e69ac7b41 Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Tue, 8 Apr 2014 17:22:18 +1000 +Subject: [PATCH] systemd: various fixes for boot with container-arrays. + +1/ Add systemd shutdown script to ensure DDF and IMSM are + clean before we actually shutdown + +2/ Get udev to tell systemd to run the mdmon@mdXXX.service + units when a member array appears. + + If we boot off a member array (with dracut at least), + the mdmon started in the initramfs will lose track of + /sys etc, so we need to restart it. + systemd will try to forget about it too (but not actually + kill it because we said not to do this). + Having udev tell it to start it will allow a new mdmon to + run which can see /sys, and systemd will know about it. + +3/ Always use --offroot and --takeover when starting mdmon with + systemd + --offroot is needed else shutdown will hang. + --takeover is needed incase an mdmon was started earlier + (e.g. in initramfs). + Neither hurt if they aren't actually needed. + +Signed-off-by: NeilBrown +--- + Makefile | 1 + + systemd/mdadm.shutdown | 4 ++++ + systemd/mdmon@.service | 12 ++++++++++-- + udev-md-raid-arrays.rules | 4 ++++ + 4 files changed, 19 insertions(+), 2 deletions(-) + create mode 100644 systemd/mdadm.shutdown + +--- mdadm-3.3.orig/Makefile ++++ mdadm-3.3/Makefile +@@ -286,6 +286,7 @@ install-udev: udev-md-raid-arrays.rules + install-systemd: systemd/mdmon@.service + $(INSTALL) -D -m 644 systemd/mdmon@.service $(DESTDIR)$(SYSTEMD_DIR)/mdmon@.service + $(INSTALL) -D -m 644 systemd/mdmonitor.service $(DESTDIR)$(SYSTEMD_DIR)/mdmonitor.service ++ $(INSTALL) -D -m 755 systemd/mdadm.shutdown $(DESTDIR)$(SYSTEMD_DIR)-shutdown/mdadm.shutdown + [ -f /etc/SuSE-release -o -n "$(SUSE)" ] && $(INSTALL) -D -m 755 systemd/SUSE-mdadm_env.sh $(DESTDIR)$(SYSTEMD_DIR)/../scripts/mdadm_env.sh || true + + uninstall: +--- /dev/null ++++ mdadm-3.3/systemd/mdadm.shutdown +@@ -0,0 +1,4 @@ ++#!/bin/sh ++# We need to ensure all md arrays with external metadata ++# (e.g. IMSM, DDF) are clean before completing the shutdown. ++/sbin/mdadm --wait-clean --scan +--- mdadm-3.3.orig/systemd/mdmon@.service ++++ mdadm-3.3/systemd/mdmon@.service +@@ -14,7 +14,15 @@ Before=initrd-switch-root.target + # mdmon should never complain due to lack of a platform, + # that is mdadm's job if at all. + Environment=IMSM_NO_PLATFORM=1 +-ExecStart=/sbin/mdmon %I ++# The mdmon starting in the initramfs (with dracut at least) ++# cannot see sysfs after root is mounted, so we will have to ++# 'takeover'. As the '--offroot --takeover' don't hurt when ++# not necessary, are are useful with root-on-md in dracut, ++# have them always present. ++ExecStart=/sbin/mdmon --offroot --takeover %I + Type=forking +-PIDFile=/run/mdadm/%I.pid ++# Don't set the PIDFile. It isn't necessary (systemd can work ++# it out) and systemd will remove it when transitioning from ++# initramfs to rootfs. ++#PIDFile=/run/mdadm/%I.pid + KillMode=none +--- mdadm-3.3.orig/udev-md-raid-arrays.rules ++++ mdadm-3.3/udev-md-raid-arrays.rules +@@ -34,4 +34,8 @@ ENV{ID_FS_USAGE}=="filesystem|other", EN + + ENV{MD_LEVEL}=="raid[1-9]*", ENV{SYSTEMD_WANTS}+="mdmonitor.service" + ++# Tell systemd to run mdmon for our container, if we need it. ++ENV{MD_LEVEL}=="raid[1-9]*", ENV{MD_CONTAINER}=="?*", PROGRAM="/usr/bin/readlink $env{MD_CONTAINER}", ENV{MD_MON_THIS}="%c" ++ENV{MD_MON_THIS}=="?*", PROGRAM="/usr/bin/basename $env{MD_MON_THIS}", ENV{SYSTEMD_WANTS}+="mdmon@%c.service" ++ + LABEL="md_end" diff --git a/0002-Assemble-re-arrange-freeing-of-tst-in-load_devices.patch b/0002-Assemble-re-arrange-freeing-of-tst-in-load_devices.patch new file mode 100644 index 0000000..1e0675c --- /dev/null +++ b/0002-Assemble-re-arrange-freeing-of-tst-in-load_devices.patch @@ -0,0 +1,89 @@ +From 9ee314dab91dc8479d2e981d0849ce777f7ea492 Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Tue, 25 Feb 2014 14:59:12 +1100 +Subject: [PATCH 2/3] Assemble: re-arrange freeing of 'tst' in load_devices(). + +When we return in error, we need to free(tst), and ->free_super(tst); +Sometimes we didn't. + +Also the final ->free_super(tst) should be followed by free(tst) +but wasn't. + +Move that file free forward in the code a bit as we will want to use +the tst there in the next patch. + +Signed-off-by: NeilBrown +--- + Assemble.c | 19 +++++++++++-------- + 1 file changed, 11 insertions(+), 8 deletions(-) + +--- mdadm-3.3.orig/Assemble.c ++++ mdadm-3.3/Assemble.c +@@ -572,6 +572,7 @@ static int load_devices(struct devs *dev + for (tmpdev = devlist; tmpdev; tmpdev=tmpdev->next) { + char *devname = tmpdev->devname; + struct stat stb; ++ struct supertype *tst; + int i; + + if (tmpdev->used != 1) +@@ -582,7 +583,6 @@ static int load_devices(struct devs *dev + int dfd; + /* prepare useful information in info structures */ + struct stat stb2; +- struct supertype *tst; + int err; + fstat(mdfd, &stb2); + +@@ -611,6 +611,8 @@ static int load_devices(struct devs *dev + close(mdfd); + free(devices); + free(devmap); ++ tst->ss->free_super(tst); ++ free(tst); + *stp = st; + return -1; + } +@@ -660,15 +662,13 @@ static int load_devices(struct devs *dev + else + bitmap_done = 1; + } +- tst->ss->free_super(tst); + } else + #endif + { +- struct supertype *tst = dup_super(st); +- int dfd; +- dfd = dev_open(devname, +- tmpdev->disposition == 'I' +- ? O_RDWR : (O_RDWR|O_EXCL)); ++ int dfd = dev_open(devname, ++ tmpdev->disposition == 'I' ++ ? O_RDWR : (O_RDWR|O_EXCL)); ++ tst = dup_super(st); + + if (dfd < 0 || tst->ss->load_super(tst, dfd, NULL) != 0) { + pr_err("cannot re-read metadata from %s - aborting\n", +@@ -678,11 +678,12 @@ static int load_devices(struct devs *dev + close(mdfd); + free(devices); + free(devmap); ++ tst->ss->free_super(tst); ++ free(tst); + *stp = st; + return -1; + } + tst->ss->getinfo_super(tst, content, devmap + devcnt * content->array.raid_disks); +- tst->ss->free_super(tst); + close(dfd); + } + +@@ -705,6 +706,8 @@ static int load_devices(struct devs *dev + > devices[most_recent].i.events) + most_recent = devcnt; + } ++ tst->ss->free_super(tst); ++ free(tst); + + if (content->array.level == LEVEL_MULTIPATH) + /* with multipath, the raid_disk from the superblock is meaningless */ diff --git a/0002-DDF-guard-against-pdnum-being-negative.patch b/0002-DDF-guard-against-pdnum-being-negative.patch new file mode 100644 index 0000000..bf93b0d --- /dev/null +++ b/0002-DDF-guard-against-pdnum-being-negative.patch @@ -0,0 +1,90 @@ +From a44e993e37a76561fa30e932b93d85fab9bcc272 Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Wed, 2 Apr 2014 13:34:10 +1100 +Subject: [PATCH 2/4] DDF: guard against ->pdnum being negative. + +It is conceivable that ->pdnum could be -1, though only if +the metadata is corrupt. +We should be careful not to use it if it is. + +Also remove an assignment for pdnum to ->container_member. +This is never used and cannot possibly mean anything. + +Signed-off-by: NeilBrown +--- + super-ddf.c | 22 ++++++++++++++++------ + 1 file changed, 16 insertions(+), 6 deletions(-) + +--- mdadm-3.3.orig/super-ddf.c ++++ mdadm-3.3/super-ddf.c +@@ -2465,7 +2465,11 @@ static struct extent *get_extents(struct + struct extent *rv; + int n = 0; + unsigned int i; +- __u16 state = be16_to_cpu(ddf->phys->entries[dl->pdnum].state); ++ __u16 state; ++ ++ if (dl->pdnum < 0) ++ return NULL; ++ state = be16_to_cpu(ddf->phys->entries[dl->pdnum].state); + + if ((state & (DDF_Online|DDF_Failed|DDF_Missing)) != DDF_Online) + return NULL; +@@ -2900,7 +2904,7 @@ static int remove_from_super_ddf(struct + if (dl->major == dk->major && + dl->minor == dk->minor) + break; +- if (!dl) ++ if (!dl || dl->pdnum < 0) + return -1; + + if (st->update_tail) { +@@ -4096,7 +4100,7 @@ static int ddf_open_new(struct supertype + if (dl->major == dev->disk.major && + dl->minor == dev->disk.minor) + break; +- if (!dl) { ++ if (!dl || dl->pdnum < 0) { + pr_err("%s: device %d/%d of subarray %d not found in meta data\n", + __func__, dev->disk.major, dev->disk.minor, n); + return -1; +@@ -4728,6 +4732,9 @@ static void ddf_process_update(struct su + for (dl = ddf->dlist; dl; dl = dl->next) { + unsigned int vn = 0; + int in_degraded = 0; ++ ++ if (dl->pdnum < 0) ++ continue; + for (vcl = ddf->conflist; vcl ; vcl = vcl->next) { + unsigned int dn, ibvd; + const struct vd_config *conf; +@@ -4991,7 +4998,11 @@ static struct mdinfo *ddf_activate_spare + int is_dedicated = 0; + struct extent *ex; + unsigned int j; +- be16 state = ddf->phys->entries[dl->pdnum].state; ++ be16 state; ++ ++ if (dl->pdnum < 0) ++ continue; ++ state = ddf->phys->entries[dl->pdnum].state; + if (be16_and(state, + cpu_to_be16(DDF_Failed|DDF_Missing)) || + !be16_and(state, +@@ -5082,7 +5093,6 @@ static struct mdinfo *ddf_activate_spare + di->recovery_start = 0; + di->data_offset = pos; + di->component_size = a->info.component_size; +- di->container_member = dl->pdnum; + di->next = rv; + rv = di; + dprintf("%x:%x (%08x) to be %d at %llu\n", +@@ -5140,7 +5150,7 @@ static struct mdinfo *ddf_activate_spare + if (dl->major == di->disk.major + && dl->minor == di->disk.minor) + break; +- if (!dl) { ++ if (!dl || dl->pdnum < 0) { + pr_err("%s: BUG: can't find disk %d (%d/%d)\n", + __func__, di->disk.raid_disk, + di->disk.major, di->disk.minor); diff --git a/0003-Assemble-change-load_devices-to-return-most_recent-s.patch b/0003-Assemble-change-load_devices-to-return-most_recent-s.patch new file mode 100644 index 0000000..53e335a --- /dev/null +++ b/0003-Assemble-change-load_devices-to-return-most_recent-s.patch @@ -0,0 +1,36 @@ +From 56bbc588f7f0f3bdd3ec23f02109b427c1d3b8f1 Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Tue, 25 Feb 2014 15:04:16 +1100 +Subject: [PATCH 3/3] Assemble: change load_devices to return most_recent 'st' + value. + +This means that + + st->ss->getinfo_super(st, content, NULL); + clean = content->array.state & 1; + +will get an up-to-date value for 'clean'. This fix allows + tests/03r5assem-failed +to work. + +Signed-off-by: NeilBrown +--- + Assemble.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- mdadm-3.3.orig/Assemble.c ++++ mdadm-3.3/Assemble.c +@@ -703,8 +703,12 @@ static int load_devices(struct devs *dev + if (devices[devcnt].i.disk.state == 6) { + if (most_recent < 0 || + devices[devcnt].i.events +- > devices[most_recent].i.events) ++ > devices[most_recent].i.events) { ++ struct supertype *tmp = tst; ++ tst = st; ++ st = tmp; + most_recent = devcnt; ++ } + } + tst->ss->free_super(tst); + free(tst); diff --git a/0003-DDF-fix-possible-mdmon-crash-when-updating-metadata.patch b/0003-DDF-fix-possible-mdmon-crash-when-updating-metadata.patch new file mode 100644 index 0000000..4490745 --- /dev/null +++ b/0003-DDF-fix-possible-mdmon-crash-when-updating-metadata.patch @@ -0,0 +1,27 @@ +From 188d31ed2b6dc195a4be1f5620ce2e5185d4e789 Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Wed, 2 Apr 2014 15:14:43 +1100 +Subject: [PATCH 3/4] DDF: fix possible mdmon crash when updating metadata. + +Testing 'c' and then using 'vdc' assumes that the two are in sync, +but sometimes they aren't. +Testing 'vdc' is safer. +This avoids a crash in some cases when failing/removing/added devices +to a DDF. + +Signed-off-by: NeilBrown +--- + super-ddf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- mdadm-3.3.orig/super-ddf.c ++++ mdadm-3.3/super-ddf.c +@@ -3000,7 +3000,7 @@ static int __write_ddf_structure(struct + (const struct vd_config **)&vdc, + &dummy); + } +- if (c) { ++ if (vdc) { + dprintf("writing conf record %i on disk %08x for %s/%u\n", + i, be32_to_cpu(d->disk.refnum), + guid_str(vdc->guid), diff --git a/0003-Work-around-architectures-having-statfs.f_type-defin.patch b/0003-Work-around-architectures-having-statfs.f_type-defin.patch new file mode 100644 index 0000000..d2a2ae3 --- /dev/null +++ b/0003-Work-around-architectures-having-statfs.f_type-defin.patch @@ -0,0 +1,38 @@ +From 76d0f1886fdef89891d617df7e7f3fde89a38e1a Mon Sep 17 00:00:00 2001 +From: Jes Sorensen +Date: Wed, 19 Mar 2014 14:26:02 +0100 +Subject: [PATCH 3/6] Work around architectures having statfs.f_type defined as + long + +Having RAMFS_MAGIC defined as 0x858458f6 causing problems when trying +to compare it directly against statfs.f_type being cast from long to +unsigned long. + +This hack is extremly ugly, but it should at least do the right thing +for every situation. + +Thanks to Arnd Bergmann for suggesting the fix. + +Signed-off-by: Jes Sorensen +Signed-off-by: NeilBrown +--- + util.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- mdadm-3.3.orig/util.c ++++ mdadm-3.3/util.c +@@ -1948,9 +1948,13 @@ int in_initrd(void) + { + /* This is based on similar function in systemd. */ + struct statfs s; ++ /* statfs.f_type is signed long on s390x and MIPS, causing all ++ sorts of sign extension problems with RAMFS_MAGIC being ++ defined as 0x858458f6 */ + return statfs("/", &s) >= 0 && + ((unsigned long)s.f_type == TMPFS_MAGIC || +- (unsigned long)s.f_type == RAMFS_MAGIC); ++ ((unsigned long)s.f_type & 0xFFFFFFFFUL) == ++ ((unsigned long)RAMFS_MAGIC & 0xFFFFFFFFUL)); + } + + void reopen_mddev(int mdfd) diff --git a/0004-DDF-Don-t-fail-compare_super_ddf-due-to-re-configure.patch b/0004-DDF-Don-t-fail-compare_super_ddf-due-to-re-configure.patch new file mode 100644 index 0000000..4735c28 --- /dev/null +++ b/0004-DDF-Don-t-fail-compare_super_ddf-due-to-re-configure.patch @@ -0,0 +1,86 @@ +From f43f5b32991c7f5a188940b00989c27f87feee81 Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Wed, 2 Apr 2014 15:26:35 +1100 +Subject: [PATCH 4/4] DDF: Don't fail compare_super_ddf due to re-configure + changes. + +It is possible that one device has seem some reconfig but the other +hasn't. In that case they are still the "same" DDF, even though +one might be older. Such age will be detected by 'seq' differences. + +If A is new and B is old, then it is import that + mdadm -I B + mdadm -I A + +doesn't get confused because A has the same uuid as B, but compare_super fails. + +So: if the seq numbers are different, then just accept as two +different superblocks. +If they are the same, then look to copy data from new to old. + +Signed-off-by: NeilBrown +--- + super-ddf.c | 44 +++++++++++--------------------------------- + 1 file changed, 11 insertions(+), 33 deletions(-) + +--- mdadm-3.3.orig/super-ddf.c ++++ mdadm-3.3/super-ddf.c +@@ -3937,47 +3937,25 @@ static int compare_super_ddf(struct supe + if (memcmp(first->anchor.guid, second->anchor.guid, DDF_GUID_LEN) != 0) + return 2; + +- if (first->max_part != second->max_part || +- !be16_eq(first->phys->used_pdes, second->phys->used_pdes) || +- !be16_eq(first->virt->populated_vdes, +- second->virt->populated_vdes)) { +- dprintf("%s: PD/VD number mismatch\n", __func__); +- return 3; +- } ++ /* It is only OK to compare info in the anchor. Anything else ++ * could be changing due to a reconfig so must be ignored. ++ * guid really should be enough anyway. ++ */ + +- max_pds = be16_to_cpu(first->phys->used_pdes); +- for (dl2 = second->dlist; dl2; dl2 = dl2->next) { +- for (pd = 0; pd < max_pds; pd++) +- if (be32_eq(first->phys->entries[pd].refnum, +- dl2->disk.refnum)) +- break; +- if (pd == max_pds) { +- dprintf("%s: no match for disk %08x\n", __func__, +- be32_to_cpu(dl2->disk.refnum)); +- return 3; +- } ++ if (!be32_eq(first->active->seq, second->active->seq)) { ++ dprintf("%s: sequence number mismatch %u<->%u\n", __func__, ++ be32_to_cpu(first->active->seq), ++ be32_to_cpu(second->active->seq)); ++ return 0; + } + +- max_vds = be16_to_cpu(first->active->max_vd_entries); +- for (vl2 = second->conflist; vl2; vl2 = vl2->next) { +- if (!be32_eq(vl2->conf.magic, DDF_VD_CONF_MAGIC)) +- continue; +- for (vd = 0; vd < max_vds; vd++) +- if (!memcmp(first->virt->entries[vd].guid, +- vl2->conf.guid, DDF_GUID_LEN)) +- break; +- if (vd == max_vds) { +- dprintf("%s: no match for VD config\n", __func__); +- return 3; +- } +- } +- /* FIXME should I look at anything else? */ +- + /* + At this point we are fairly sure that the meta data matches. + But the new disk may contain additional local data. + Add it to the super block. + */ ++ max_vds = be16_to_cpu(first->active->max_vd_entries); ++ max_pds = be16_to_cpu(first->phys->used_pdes); + for (vl2 = second->conflist; vl2; vl2 = vl2->next) { + for (vl1 = first->conflist; vl1; vl1 = vl1->next) + if (!memcmp(vl1->conf.guid, vl2->conf.guid, diff --git a/0004-DDF-report-seq-counter-as-events.patch b/0004-DDF-report-seq-counter-as-events.patch new file mode 100644 index 0000000..aa54196 --- /dev/null +++ b/0004-DDF-report-seq-counter-as-events.patch @@ -0,0 +1,56 @@ +From eba2859f50bc0de6da7938a9ec6cfe4ceef43874 Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Wed, 26 Mar 2014 14:19:43 +1100 +Subject: [PATCH 4/6] DDF: report seq counter as events. + +Also don't treat two devices with different seq numbers as completely +unrelated. + +This allows split-brain detection to work properly for ddf. + +Signed-off-by: NeilBrown +--- + super-ddf.c | 11 ++++------- + 1 file changed, 4 insertions(+), 7 deletions(-) + +--- mdadm-3.3.orig/super-ddf.c ++++ mdadm-3.3/super-ddf.c +@@ -1929,6 +1929,8 @@ static void getinfo_super_ddf(struct sup + info->disk.state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE); + else + info->disk.state = 1 << MD_DISK_FAULTY; ++ ++ info->events = be32_to_cpu(ddf->active->seq); + } else { + info->disk.number = -1; + info->disk.raid_disk = -1; +@@ -2029,6 +2031,7 @@ static void getinfo_super_ddf_bvd(struct + (be16_to_cpu(ddf->phys->entries[info->disk.number].state) & DDF_Online) && + !(be16_to_cpu(ddf->phys->entries[info->disk.number].state) & DDF_Failed)) + info->disk.state = (1<events = be32_to_cpu(ddf->active->seq); + } + + info->container_member = ddf->currentconf->vcnum; +@@ -3841,7 +3844,7 @@ static struct mdinfo *container_content_ + dev->disk.state = (1<recovery_start = MaxSector; + +- dev->events = be32_to_cpu(ddf->primary.seq); ++ dev->events = be32_to_cpu(ddf->active->seq); + dev->data_offset = + be64_to_cpu(LBA_OFFSET(ddf, bvd)[iphys]); + dev->component_size = be64_to_cpu(bvd->blocks); +@@ -3928,12 +3931,6 @@ static int compare_super_ddf(struct supe + if (memcmp(first->anchor.guid, second->anchor.guid, DDF_GUID_LEN) != 0) + return 2; + +- if (!be32_eq(first->active->seq, second->active->seq)) { +- dprintf("%s: sequence number mismatch %u<->%u\n", __func__, +- be32_to_cpu(first->active->seq), +- be32_to_cpu(second->active->seq)); +- return 3; +- } + if (first->max_part != second->max_part || + !be16_eq(first->phys->used_pdes, second->phys->used_pdes) || + !be16_eq(first->virt->populated_vdes, diff --git a/0005-DDF-when-first-activating-an-array-record-any-missin.patch b/0005-DDF-when-first-activating-an-array-record-any-missin.patch new file mode 100644 index 0000000..fe8b2d8 --- /dev/null +++ b/0005-DDF-when-first-activating-an-array-record-any-missin.patch @@ -0,0 +1,65 @@ +From 5a46fcd7f5b1bd1bf190784f112a15f383262af5 Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Wed, 26 Mar 2014 14:26:53 +1100 +Subject: [PATCH 5/6] DDF: when first activating an array, record any missing + devices. + +We must remember they are missing so that if they re-appear we +don't get confused. + +Signed-off-by: NeilBrown +--- + super-ddf.c | 28 ++++++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +--- mdadm-3.3.orig/super-ddf.c ++++ mdadm-3.3/super-ddf.c +@@ -511,6 +511,8 @@ static void pr_state(const struct ddf_su + + static void _ddf_set_updates_pending(struct ddf_super *ddf, const char *func) + { ++ if (ddf->updates_pending) ++ return; + ddf->updates_pending = 1; + ddf->active->seq = cpu_to_be32((be32_to_cpu(ddf->active->seq)+1)); + pr_state(ddf, func); +@@ -4115,6 +4117,31 @@ static int ddf_open_new(struct supertype + return 0; + } + ++static void handle_missing(struct ddf_super *ddf, int inst) ++{ ++ /* This member array is being activated. If any devices ++ * are missing they must now be marked as failed. ++ */ ++ struct vd_config *vc; ++ unsigned int n_bvd; ++ struct vcl *vcl; ++ struct dl *dl; ++ int n; ++ ++ for (n = 0; ; n++) { ++ vc = find_vdcr(ddf, inst, n, &n_bvd, &vcl); ++ if (!vc) ++ break; ++ for (dl = ddf->dlist; dl; dl = dl->next) ++ if (be32_eq(dl->disk.refnum, vc->phys_refnum[n_bvd])) ++ break; ++ if (dl) ++ /* Found this disk, so not missing */ ++ continue; ++ vc->phys_refnum[n_bvd] = cpu_to_be32(0); ++ } ++} ++ + /* + * The array 'a' is to be marked clean in the metadata. + * If '->resync_start' is not ~(unsigned long long)0, then the array is only +@@ -4130,6 +4157,7 @@ static int ddf_set_array_state(struct ac + int inst = a->info.container_member; + int old = ddf->virt->entries[inst].state; + if (consistent == 2) { ++ handle_missing(ddf, inst); + /* Should check if a recovery should be started FIXME */ + consistent = 1; + if (!is_resync_complete(&a->info)) diff --git a/mdadm.changes b/mdadm.changes index cb8b4f2..6250267 100644 --- a/mdadm.changes +++ b/mdadm.changes @@ -1,3 +1,38 @@ +------------------------------------------------------------------- +Tue Apr 8 07:38:42 UTC 2014 - nfbrown@suse.com + +- 0001-systemd-various-fixes-for-boot-with-container-arrays.patch + various fixes to improve boot-from-DDF or IMSM + (bnc#866660) + +------------------------------------------------------------------- +Wed Apr 2 04:41:53 UTC 2014 - nfbrown@suse.com + +- 0001-DDF-mark-missing-on-assembly-device-properly.patch +- 0002-DDF-guard-against-pdnum-being-negative.patch +- 0003-DDF-fix-possible-mdmon-crash-when-updating-metadata.patch +- 0004-DDF-Don-t-fail-compare_super_ddf-due-to-re-configure.patch + More upstream DDF fixes (bnc#866660) + +------------------------------------------------------------------- +Wed Mar 26 04:00:51 UTC 2014 - nfbrown@suse.com + +- 0001-mdmon-.service-Change-type-of-process-start-up-to-fo.patch +- 0003-Work-around-architectures-having-statfs.f_type-defin.patch +- 0004-DDF-report-seq-counter-as-events.patch +- 0005-DDF-when-first-activating-an-array-record-any-missin.patch + Two fixes for DDF (bnc#866660) and a couple of other upstream fixes + just for good measure. + +------------------------------------------------------------------- +Tue Mar 4 22:48:20 UTC 2014 - nfbrown@suse.com + +- 0001-Assemble-allow-load_devices-to-change-the-st-which-i.patch + 0002-Assemble-re-arrange-freeing-of-tst-in-load_devices.patch + 0003-Assemble-change-load_devices-to-return-most_recent-s.patch + Allow RAID5 to be assembled even when firs device listed recently + failed (bnc#865221) + ------------------------------------------------------------------- Wed Jan 22 23:45:34 UTC 2014 - nfbrown@suse.com diff --git a/mdadm.shutdown b/mdadm.shutdown deleted file mode 100644 index 38b5c5b..0000000 --- a/mdadm.shutdown +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -# We need to ensure all md array with external metadata -# (e.g. IMSM) are clean before completing the shutdown. -/sbin/mdadm --wait-clean --scan diff --git a/mdadm.spec b/mdadm.spec index ac80512..31308a8 100644 --- a/mdadm.spec +++ b/mdadm.spec @@ -40,7 +40,6 @@ Source2: sysconfig.mdadm 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 @@ -99,6 +98,30 @@ Patch26: mdmon-don-t-complain-about-notifying-parent-when-the.patch Patch27: systemd-mdmon-set-IMSM_NO_PLATFORM-1.patch # PATCH-FIX-UPSTREAM mdmon-.service-remove-over-ride-of-Standard-IO.patch nfbrown@suse.de Patch28: mdmon-.service-remove-over-ride-of-Standard-IO.patch +# PATCH-FIX-UPSTREAM 0001-Assemble-allow-load_devices-to-change-the-st-which-i.patch bnc#865221 nfbrown@suse.de +Patch32: 0001-Assemble-allow-load_devices-to-change-the-st-which-i.patch +# PATCH-FIX-UPSTREAM 0002-Assemble-re-arrange-freeing-of-tst-in-load_devices.patch bnc#865221 nfbrown@suse.de +Patch33: 0002-Assemble-re-arrange-freeing-of-tst-in-load_devices.patch +# PATCH-FIX-UPSTREAM 0003-Assemble-change-load_devices-to-return-most_recent-s.patch bnc#865221 nfbrown@suse.de +Patch34: 0003-Assemble-change-load_devices-to-return-most_recent-s.patch +# PATCH-FIX-UPSTREAM 0001-mdmon-.service-Change-type-of-process-start-up-to-fo.patch nfbrown@suse.de +Patch35: 0001-mdmon-.service-Change-type-of-process-start-up-to-fo.patch +# PATCH-FIX-UPSTREAM 0003-Work-around-architectures-having-statfs.f_type-defin.patch nfbrown@suse.de +Patch36: 0003-Work-around-architectures-having-statfs.f_type-defin.patch +# PATCH-FIX-UPSTREAM 0004-DDF-report-seq-counter-as-events.patch bnc#866660 nfbrown@suse.de +Patch37: 0004-DDF-report-seq-counter-as-events.patch +# PATCH-FIX-UPSTREAM 0005-DDF-when-first-activating-an-array-record-any-missin.patch bnc#866660 nfbrown@suse.de +Patch38: 0005-DDF-when-first-activating-an-array-record-any-missin.patch +# PATCH-FIX-UPSTREAM 0001-DDF-mark-missing-on-assembly-device-properly.patch bnc#866660 nfbrown@suse.de +Patch39: 0001-DDF-mark-missing-on-assembly-device-properly.patch +# PATCH-FIX-UPSTREAM 0002-DDF-guard-against-pdnum-being-negative.patch bnc#866660 nfbrown@suse.de +Patch40: 0002-DDF-guard-against-pdnum-being-negative.patch +# PATCH-FIX-UPSTREAM 0003-DDF-fix-possible-mdmon-crash-when-updating-metadata.patch bnc#866660 nfbrown@suse.de +Patch41: 0003-DDF-fix-possible-mdmon-crash-when-updating-metadata.patch +# PATCH-FIX-UPSTREAM 0004-DDF-Don-t-fail-compare_super_ddf-due-to-re-configure.patch bnc#866660 nfbrown@suse.de +Patch42: 0004-DDF-Don-t-fail-compare_super_ddf-due-to-re-configure.patch +# PATCH-FIX-UPSTREAM 0001-systemd-various-fixes-for-boot-with-container-arrays.patch bnc#866660 nfbrown@suse.de +Patch43: 0001-systemd-various-fixes-for-boot-with-container-arrays.patch %define _udevdir %(pkg-config --variable=udevdir udev) %define _systemdshutdowndir %{_unitdir}/../system-shutdown @@ -138,6 +161,18 @@ programs but with a very different interface. %patch26 -p1 %patch27 -p1 %patch28 -p1 +%patch32 -p1 +%patch33 -p1 +%patch34 -p1 +%patch35 -p1 +%patch36 -p1 +%patch37 -p1 +%patch38 -p1 +%patch39 -p1 +%patch40 -p1 +%patch41 -p1 +%patch42 -p1 +%patch43 -p1 %build make %{?_smp_mflags} CC="%__cc" CXFLAGS="$RPM_OPT_FLAGS -Wno-error" SUSE=yes @@ -157,7 +192,6 @@ install -d %{buildroot}/etc/cron.daily install -m 755 %{S:7} %{buildroot}/etc/cron.daily/mdadm install -m 644 %{S:2} %{buildroot}%{_var}/adm/fillup-templates/ 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