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 <dan.j.williams@intel.com>
This commit is contained in:
Dan Williams 2010-05-26 13:22:36 -07:00
parent 4460f8f7c3
commit 97b4d0e971
4 changed files with 92 additions and 21 deletions

View File

@ -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.
*/

View File

@ -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;

View File

@ -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;

View File

@ -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;