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