[PATCH] imsm: finish recovery when drive with rebuild fails

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 <mariusz.tkaczyk@xxxxxxxxx>
---
 super-intel.c | 26 +++++++++++---------------
 1 file changed, 11 insertions(+), 15 deletions(-)

diff --git a/super-intel.c b/super-intel.c
index d2035ccd..38a1b6cc 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




[Index of Archives]     [Linux RAID Wiki]     [ATA RAID]     [Linux SCSI Target Infrastructure]     [Linux Block]     [Linux IDE]     [Linux SCSI]     [Linux Hams]     [Device Mapper]     [Device Mapper Cryptographics]     [Kernel]     [Linux Admin]     [Linux Net]     [GFS]     [RPM]     [git]     [Yosemite Forum]


  Powered by Linux