From 7733b91d37e73f7b965ec41bc257ba7b76835439 Mon Sep 17 00:00:00 2001 From: "mwilck@arcor.de" Date: Thu, 25 Jul 2013 20:59:11 +0200 Subject: DDF: ddf_activate_spare: Add RAID10 code The check for degraded array is a bit more complex for RAID10. Fixing it. Signed-off-by: NeilBrown --- super-ddf.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) (limited to 'super-ddf.c') diff --git a/super-ddf.c b/super-ddf.c index ac30e4e5..13a2e61a 100644 --- a/super-ddf.c +++ b/super-ddf.c @@ -4654,6 +4654,55 @@ static void ddf_prepare_update(struct supertype *st, } } +/* + * Check degraded state of a RAID10. + * returns 2 for good, 1 for degraded, 0 for failed, and -1 for error + */ +static int raid10_degraded(struct mdinfo *info) +{ + int n_prim, n_bvds; + int i; + struct mdinfo *d, *sra; + char *found; + int ret = -1; + + if (info->array.layout == 0) { + sra = sysfs_read(-1, info->sys_name, GET_LAYOUT); + info->array.layout = sra->array.layout; + free(sra); + } + + n_prim = info->array.layout & ~0x100; + n_bvds = info->array.raid_disks / n_prim; + found = xmalloc(n_bvds); + if (found == NULL) + return ret; + memset(found, 0, n_bvds); + for (d = info->devs; d; d = d->next) { + i = d->disk.raid_disk / n_prim; + if (i >= n_bvds) { + pr_err("%s: BUG: invalid raid disk\n", __func__); + goto out; + } + if (d->state_fd > 0) + found[i]++; + } + ret = 2; + for (i = 0; i < n_bvds; i++) + if (!found[i]) { + dprintf("%s: BVD %d/%d failed\n", __func__, i, n_bvds); + ret = 0; + goto out; + } else if (found[i] < n_prim) { + dprintf("%s: BVD %d/%d degraded\n", __func__, i, + n_bvds); + ret = 1; + } +out: + free(found); + return ret; +} + /* * Check if the array 'a' is degraded but not failed. * If it is, find as many spares as are available and needed and @@ -4694,7 +4743,7 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a, working ++; } - dprintf("ddf_activate: working=%d (%d) level=%d\n", working, + dprintf("%s: working=%d (%d) level=%d\n", __func__, working, a->info.array.raid_disks, a->info.array.level); if (working == a->info.array.raid_disks) @@ -4713,6 +4762,10 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a, if (working < a->info.array.raid_disks - 2) return NULL; /* failed */ break; + case 10: + if (raid10_degraded(&a->info) < 1) + return NULL; + break; default: /* concat or stripe */ return NULL; /* failed */ } -- cgit v1.2.3