Blame SOURCES/imsm-continue-resync-on-3disk-RAID10.patch

2c1b57
commit 8b9cd157dc030924afaeb1dd1a4d3306f5bda118
2c1b57
Author: Maksymilian Kunt <maksymilian.kunt@intel.com>
2c1b57
Date:   Mon Nov 13 12:30:49 2017 +0100
2c1b57
2c1b57
    imsm: continue resync on 3-disk RAID10
2c1b57
    
2c1b57
    If RAID10 gets degraded during resync and is stopped, it doesn't continue
2c1b57
    resync after automatic assemble and it is reported to be in sync. Resync
2c1b57
    is blocked because the disk is missing. It should not happen for RAID10 as
2c1b57
    it can still continue with 3 disks.
2c1b57
    
2c1b57
    Count missing disks. Block resync only if number of missing disks exceeds
2c1b57
    limit for given RAID level (only different for RAID10). Check if the
2c1b57
    disk under recovery is present. If not, resync should be allowed to run.
2c1b57
    
2c1b57
    Signed-off-by: Maksymilian Kunt <maksymilian.kunt@intel.com>
2c1b57
    Signed-off-by: Tomasz Majchrzak <tomasz.majchrzak@intel.com>
2c1b57
    Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2c1b57
2c1b57
diff --git a/super-intel.c b/super-intel.c
2c1b57
index 2f912f2..c55802f 100644
2c1b57
--- a/super-intel.c
2c1b57
+++ b/super-intel.c
2c1b57
@@ -1342,6 +1342,20 @@ static unsigned long long round_size_to_mb(unsigned long long size, unsigned int
2c1b57
 	return size;
2c1b57
 }
2c1b57
 
2c1b57
+static int able_to_resync(int raid_level, int missing_disks)
2c1b57
+{
2c1b57
+	int max_missing_disks = 0;
2c1b57
+
2c1b57
+	switch (raid_level) {
2c1b57
+	case 10:
2c1b57
+		max_missing_disks = 1;
2c1b57
+		break;
2c1b57
+	default:
2c1b57
+		max_missing_disks = 0;
2c1b57
+	}
2c1b57
+	return missing_disks <= max_missing_disks;
2c1b57
+}
2c1b57
+
2c1b57
 /* try to determine how much space is reserved for metadata from
2c1b57
  * the last get_extents() entry on the smallest active disk,
2c1b57
  * otherwise fallback to the default
2c1b57
@@ -7645,6 +7659,7 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra
2c1b57
 		int slot;
2c1b57
 		int chunk;
2c1b57
 		char *ep;
2c1b57
+		int level;
2c1b57
 
2c1b57
 		if (subarray &&
2c1b57
 		    (i != strtoul(subarray, &ep, 10) || *ep != '\0'))
2c1b57
@@ -7653,6 +7668,7 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra
2c1b57
 		dev = get_imsm_dev(super, i);
2c1b57
 		map = get_imsm_map(dev, MAP_0);
2c1b57
 		map2 = get_imsm_map(dev, MAP_1);
2c1b57
+		level = get_imsm_raid_level(map);
2c1b57
 
2c1b57
 		/* do not publish arrays that are in the middle of an
2c1b57
 		 * unsupported migration
2c1b57
@@ -7675,8 +7691,8 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra
2c1b57
 		chunk = __le16_to_cpu(map->blocks_per_strip) >> 1;
2c1b57
 		/* mdadm does not support all metadata features- set the bit in all arrays state */
2c1b57
 		if (!validate_geometry_imsm_orom(super,
2c1b57
-						 get_imsm_raid_level(map), /* RAID level */
2c1b57
-						 imsm_level_to_layout(get_imsm_raid_level(map)),
2c1b57
+						 level, /* RAID level */
2c1b57
+						 imsm_level_to_layout(level),
2c1b57
 						 map->num_members, /* raid disks */
2c1b57
 						 &chunk, join_u32(dev->size_low, dev->size_high),
2c1b57
 						 1 /* verbose */)) {
2c1b57
@@ -7700,6 +7716,7 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra
2c1b57
 			int idx;
2c1b57
 			int skip;
2c1b57
 			__u32 ord;
2c1b57
+			int missing = 0;
2c1b57
 
2c1b57
 			skip = 0;
2c1b57
 			idx = get_imsm_disk_idx(dev, slot, MAP_0);
2c1b57
@@ -7713,19 +7730,27 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra
2c1b57
 				skip = 1;
2c1b57
 			if (d && is_failed(&d->disk))
2c1b57
 				skip = 1;
2c1b57
-			if (ord & IMSM_ORD_REBUILD)
2c1b57
+			if (!skip && (ord & IMSM_ORD_REBUILD))
2c1b57
 				recovery_start = 0;
2c1b57
 
2c1b57
 			/*
2c1b57
 			 * if we skip some disks the array will be assmebled degraded;
2c1b57
 			 * reset resync start to avoid a dirty-degraded
2c1b57
 			 * situation when performing the intial sync
2c1b57
-			 *
2c1b57
-			 * FIXME handle dirty degraded
2c1b57
 			 */
2c1b57
-			if ((skip || recovery_start == 0) &&
2c1b57
-			    !(dev->vol.dirty & RAIDVOL_DIRTY))
2c1b57
-				this->resync_start = MaxSector;
2c1b57
+			if (skip)
2c1b57
+				missing++;
2c1b57
+
2c1b57
+			if (!(dev->vol.dirty & RAIDVOL_DIRTY)) {
2c1b57
+				if ((!able_to_resync(level, missing) ||
2c1b57
+				     recovery_start == 0))
2c1b57
+					this->resync_start = MaxSector;
2c1b57
+			} else {
2c1b57
+				/*
2c1b57
+				 * FIXME handle dirty degraded
2c1b57
+				 */
2c1b57
+			}
2c1b57
+
2c1b57
 			if (skip)
2c1b57
 				continue;
2c1b57