summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2010-05-26 13:22:36 -0700
committerDan Williams <dan.j.williams@intel.com>2010-05-26 13:22:36 -0700
commit97b4d0e971b20cea66b4a2dd04968cae79a3c2e6 (patch)
tree431f304f86a6f2b4cc89941b655506e99b29baa5
parent4460f8f7c344a0e8c8d454edcaf392e85912c76e (diff)
downloadmdadm-97b4d0e971b20cea66b4a2dd04968cae79a3c2e6.tar.gz
mdadm-97b4d0e971b20cea66b4a2dd04968cae79a3c2e6.tar.xz
mdadm-97b4d0e971b20cea66b4a2dd04968cae79a3c2e6.zip
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>
-rw-r--r--Incremental.c9
-rw-r--r--mdadm.h4
-rw-r--r--super-ddf.c1
-rw-r--r--super-intel.c99
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;