From 97b4d0e971b20cea66b4a2dd04968cae79a3c2e6 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 26 May 2010 13:22:36 -0700 Subject: Incremental: honor an 'enough' flag from external handlers This is needed for imsm where: 1/ we want to report raid_disks as zero to allow mdadm -As to incorporate all spares 2/ we can't determine stale disks by looking at the event counts. 3/ we can't see per-subarray expectations with the info returned from the container level ->getinfo_super() Signed-off-by: Dan Williams --- Incremental.c | 9 ++++++ mdadm.h | 4 ++- super-ddf.c | 1 + super-intel.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++------------ 4 files changed, 92 insertions(+), 21 deletions(-) diff --git a/Incremental.c b/Incremental.c index 7ad648a..adef44e 100644 --- a/Incremental.c +++ b/Incremental.c @@ -258,6 +258,15 @@ int Incremental(char *devname, int verbose, int runstop, autof = ci->autof; if (st->ss->container_content && st->loaded_container) { + if ((runstop > 0 && info.container_enough >= 0) || + info.container_enough > 0) + /* pass */; + else { + if (verbose) + fprintf(stderr, Name ": not enough devices to start the container\n"); + return 1; + } + /* This is a pre-built container array, so we do something * rather different. */ diff --git a/mdadm.h b/mdadm.h index d9d17b0..a0797e8 100644 --- a/mdadm.h +++ b/mdadm.h @@ -205,7 +205,9 @@ struct mdinfo { int container_member; /* for assembling external-metatdata arrays * This is to be used internally by metadata * handler only */ - + int container_enough; /* flag external handlers can set to + * indicate that subarrays have not enough (-1), + * enough to start (0), or all expected disks (1) */ char sys_name[20]; struct mdinfo *devs; struct mdinfo *next; diff --git a/super-ddf.c b/super-ddf.c index 0e6f1e5..b01c68d 100644 --- a/super-ddf.c +++ b/super-ddf.c @@ -1357,6 +1357,7 @@ static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info) (ddf->anchor.guid+16)); info->array.utime = 0; info->array.chunk_size = 0; + info->container_enough = 0; info->disk.major = 0; diff --git a/super-intel.c b/super-intel.c index bdd7a96..88ffb52 100644 --- a/super-intel.c +++ b/super-intel.c @@ -344,7 +344,6 @@ static struct imsm_disk *__get_imsm_disk(struct imsm_super *mpb, __u8 index) return &mpb->disk[index]; } -#ifndef MDASSEMBLE /* retrieve a disk from the parsed metadata */ static struct imsm_disk *get_imsm_disk(struct intel_super *super, __u8 index) { @@ -356,7 +355,6 @@ static struct imsm_disk *get_imsm_disk(struct intel_super *super, __u8 index) return NULL; } -#endif /* generate a checksum directly from the anchor when the anchor is known to be * up-to-date, currently only at load or write_super after coalescing @@ -1528,6 +1526,20 @@ static void fixup_container_spare_uuid(struct mdinfo *inf) } } + +static __u8 imsm_check_degraded(struct intel_super *super, struct imsm_dev *dev, int failed); +static int imsm_count_failed(struct intel_super *super, struct imsm_dev *dev); + +static struct imsm_disk *get_imsm_missing(struct intel_super *super, __u8 index) +{ + struct dl *d; + + for (d = super->missing; d; d = d->next) + if (d->index == index) + return &d->disk; + return NULL; +} + static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info) { struct intel_super *super = st->sb; @@ -1562,6 +1574,53 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info) info->name[0] = 0; info->recovery_start = MaxSector; + /* do we have the all the insync disks that we expect? */ + if (st->loaded_container) { + struct imsm_super *mpb = super->anchor; + int max_enough = -1, i; + + for (i = 0; i < mpb->num_raid_devs; i++) { + struct imsm_dev *dev = get_imsm_dev(super, i); + int failed, enough, j, missing = 0; + struct imsm_map *map; + __u8 state; + + failed = imsm_count_failed(super, dev); + state = imsm_check_degraded(super, dev, failed); + map = get_imsm_map(dev, dev->vol.migr_state); + + /* any newly missing disks? + * (catches single-degraded vs double-degraded) + */ + for (j = 0; j < map->num_members; j++) { + __u32 ord = get_imsm_ord_tbl_ent(dev, i); + __u32 idx = ord_to_idx(ord); + + if (!(ord & IMSM_ORD_REBUILD) && + get_imsm_missing(super, idx)) { + missing = 1; + break; + } + } + + if (state == IMSM_T_STATE_FAILED) + enough = -1; + else if (state == IMSM_T_STATE_DEGRADED && + (state != map->map_state || missing)) + enough = 0; + else /* we're normal, or already degraded */ + enough = 1; + + /* in the missing/failed disk case check to see + * if at least one array is runnable + */ + max_enough = max(max_enough, enough); + } + dprintf("%s: enough: %d\n", __func__, max_enough); + info->container_enough = max_enough; + } else + info->container_enough = -1; + if (super->disks) { __u32 reserved = imsm_reserved_sectors(super, super->disks); @@ -4175,24 +4234,6 @@ static struct mdinfo *container_content_imsm(struct supertype *st) } -#ifndef MDASSEMBLE -static int imsm_open_new(struct supertype *c, struct active_array *a, - char *inst) -{ - struct intel_super *super = c->sb; - struct imsm_super *mpb = super->anchor; - - if (atoi(inst) >= mpb->num_raid_devs) { - fprintf(stderr, "%s: subarry index %d, out of range\n", - __func__, atoi(inst)); - return -ENODEV; - } - - dprintf("imsm: open_new %s\n", inst); - a->info.container_member = atoi(inst); - return 0; -} - static __u8 imsm_check_degraded(struct intel_super *super, struct imsm_dev *dev, int failed) { struct imsm_map *map = get_imsm_map(dev, 0); @@ -4291,6 +4332,24 @@ static int imsm_count_failed(struct intel_super *super, struct imsm_dev *dev) return failed; } +#ifndef MDASSEMBLE +static int imsm_open_new(struct supertype *c, struct active_array *a, + char *inst) +{ + struct intel_super *super = c->sb; + struct imsm_super *mpb = super->anchor; + + if (atoi(inst) >= mpb->num_raid_devs) { + fprintf(stderr, "%s: subarry index %d, out of range\n", + __func__, atoi(inst)); + return -ENODEV; + } + + dprintf("imsm: open_new %s\n", inst); + a->info.container_member = atoi(inst); + return 0; +} + static int is_resyncing(struct imsm_dev *dev) { struct imsm_map *migr_map; -- cgit