diff --git a/0010-imsm-finish-recovery-when-drive-with-rebuild-fails.patch b/0010-imsm-finish-recovery-when-drive-with-rebuild-fails.patch new file mode 100644 index 0000000..47fc81a --- /dev/null +++ b/0010-imsm-finish-recovery-when-drive-with-rebuild-fails.patch @@ -0,0 +1,98 @@ +From a4e96fd8f3f0b5416783237c1cb6ee87e7eff23d Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Fri, 8 Feb 2019 11:07:10 +0100 +Subject: [PATCH] imsm: finish recovery when drive with rebuild fails +Git-commit: a4e96fd8f3f0b5416783237c1cb6ee87e7eff23d +Patch-mainline: mdadm-4.1-12 +References: bsc#1126975 + +Commit d7a1fda2769b ("imsm: update metadata correctly while raid10 double +degradation") resolves main Imsm double degradation problems but it +omits one case. Now metadata hangs in the rebuilding state if the drive +under rebuild is removed during recovery from double degradation. + +The root cause of this problem is comparing new map_state with current +and if they both are degraded assuming that nothing new happens. + +Don't rely on map states, just check if device is failed. If the drive +under rebuild fails then finish migration, in other cases update map +state only (second fail means that destination map state can't be normal). + +To avoid problems with reassembling move end_migration (called after +double degradation successful recovery) after check if recovery really +finished, for details see (7ce057018 "imsm: fix: rebuild does not +continue after reboot"). +Remove redundant code responsible for finishing rebuild process. Function +end_migration do exactly the same. Set last_checkpoint to 0, to prepare +it for the next rebuild. + +Signed-off-by: Mariusz Tkaczyk +Signed-off-by: Jes Sorensen +Signed-off-by: Coly Li +--- + super-intel.c | 26 +++++++++++--------------- + 1 file changed, 11 insertions(+), 15 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index d2035cc..38a1b6c 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -8560,26 +8560,22 @@ static void imsm_set_disk(struct active_array *a, int n, int state) + } + if (is_rebuilding(dev)) { + dprintf_cont("while rebuilding "); +- if (map->map_state != map_state) { +- dprintf_cont("map state change "); ++ if (state & DS_FAULTY) { ++ dprintf_cont("removing failed drive "); + if (n == map->failed_disk_num) { + dprintf_cont("end migration"); + end_migration(dev, super, map_state); ++ a->last_checkpoint = 0; + } else { +- dprintf_cont("raid10 double degradation, map state change"); ++ dprintf_cont("fail detected during rebuild, changing map state"); + map->map_state = map_state; + } + super->updates_pending++; +- } else if (!rebuild_done) +- break; +- else if (n == map->failed_disk_num) { +- /* r10 double degraded to degraded transition */ +- dprintf_cont("raid10 double degradation end migration"); +- end_migration(dev, super, map_state); +- a->last_checkpoint = 0; +- super->updates_pending++; + } + ++ if (!rebuild_done) ++ break; ++ + /* check if recovery is really finished */ + for (mdi = a->info.devs; mdi ; mdi = mdi->next) + if (mdi->recovery_start != MaxSector) { +@@ -8588,7 +8584,7 @@ static void imsm_set_disk(struct active_array *a, int n, int state) + } + if (recovery_not_finished) { + dprintf_cont("\n"); +- dprintf_cont("Rebuild has not finished yet, map state changes only if raid10 double degradation happens"); ++ dprintf_cont("Rebuild has not finished yet"); + if (a->last_checkpoint < mdi->recovery_start) { + a->last_checkpoint = + mdi->recovery_start; +@@ -8598,9 +8594,9 @@ static void imsm_set_disk(struct active_array *a, int n, int state) + } + + dprintf_cont(" Rebuild done, still degraded"); +- dev->vol.migr_state = 0; +- set_migr_type(dev, 0); +- dev->vol.curr_migr_unit = 0; ++ end_migration(dev, super, map_state); ++ a->last_checkpoint = 0; ++ super->updates_pending++; + + for (i = 0; i < map->num_members; i++) { + int idx = get_imsm_ord_tbl_ent(dev, i, MAP_0); +-- +2.16.4 + diff --git a/0011-mdmon-don-t-attempt-to-manage-new-arrays-when-termin.patch b/0011-mdmon-don-t-attempt-to-manage-new-arrays-when-termin.patch new file mode 100644 index 0000000..fd31b0a --- /dev/null +++ b/0011-mdmon-don-t-attempt-to-manage-new-arrays-when-termin.patch @@ -0,0 +1,53 @@ +From 69d084784de196acec8ab703cd1b379af211d624 Mon Sep 17 00:00:00 2001 +From: Artur Paszkiewicz +Date: Fri, 22 Feb 2019 10:15:45 +0100 +Subject: [PATCH] mdmon: don't attempt to manage new arrays when terminating +Git-commit: 69d084784de196acec8ab703cd1b379af211d624 +Patch-mainline: mdadm-4.1-12 +References: bsc#1127526 + +When mdmon gets a SIGTERM, it stops managing arrays that are clean. If +there is more that one array in the container and one of them is dirty +and the clean one is still present in mdstat, mdmon will treat it as a +new array and start managing it again. This leads to a cycle of +remove_old() / manage_new() calls for the clean array, until the other +one also becomes clean. + +Prevent this by not calling manage_new() if sigterm is set. Also, remove +a check for sigterm in manage_new() because the condition will never be +true. + +Signed-off-by: Artur Paszkiewicz +Signed-off-by: Jes Sorensen +Signed-off-by: Coly Li +--- + managemon.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/managemon.c b/managemon.c +index 101231c..29b91ba 100644 +--- a/managemon.c ++++ b/managemon.c +@@ -727,9 +727,7 @@ static void manage_new(struct mdstat_ent *mdstat, + dprintf("inst: %s action: %d state: %d\n", inst, + new->action_fd, new->info.state_fd); + +- if (sigterm) +- new->info.safe_mode_delay = 1; +- else if (mdi->safe_mode_delay >= 50) ++ if (mdi->safe_mode_delay >= 50) + /* Normal start, mdadm set this. */ + new->info.safe_mode_delay = mdi->safe_mode_delay; + else +@@ -803,7 +801,7 @@ void manage(struct mdstat_ent *mdstat, struct supertype *container) + break; + } + } +- if (a == NULL || !a->container) ++ if ((a == NULL || !a->container) && !sigterm) + manage_new(mdstat, container, a); + } + } +-- +2.16.4 + diff --git a/mdadm.changes b/mdadm.changes index eaba98b..6cafc94 100644 --- a/mdadm.changes +++ b/mdadm.changes @@ -1,3 +1,12 @@ +------------------------------------------------------------------- +Thu Mar 28 11:43:38 UTC 2019 - colyli@suse.com + +- imsm: finish recovery when drive with rebuild fails (bsc#1126975) + 0010-imsm-finish-recovery-when-drive-with-rebuild-fails.patch +- mdmon: don't attempt to manage new arrays when terminating + (bsc#1127526) + 0011-mdmon-don-t-attempt-to-manage-new-arrays-when-termin.patch + ------------------------------------------------------------------- Tue Feb 12 06:21:48 UTC 2019 - colyli@suse.com diff --git a/mdadm.spec b/mdadm.spec index fb22de1..5a89926 100644 --- a/mdadm.spec +++ b/mdadm.spec @@ -51,6 +51,8 @@ Patch16: 0006-Grow-avoid-overflow-in-compute_backup_blocks.patch Patch17: 0007-Grow-report-correct-new-chunk-size.patch Patch18: 0008-policy.c-prevent-NULL-pointer-referencing.patch Patch19: 0009-Detail.c-do-not-skip-first-character-when-calling-xs.patch +Patch20: 0010-imsm-finish-recovery-when-drive-with-rebuild-fails.patch +Patch21: 0011-mdmon-don-t-attempt-to-manage-new-arrays-when-termin.patch Patch1001: 1001-display-timeout-status.patch %define _udevdir %(pkg-config --variable=udevdir udev) %define _systemdshutdowndir %{_unitdir}/../system-shutdown @@ -70,6 +72,8 @@ mdadm is a program that can be used to control Linux md devices. %patch17 -p1 %patch18 -p1 %patch19 -p1 +%patch20 -p1 +%patch21 -p1 %patch1001 -p1 %build