This reverts commit 4dde420fc3e24077ab926f79674eaae1b71de10b. Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@xxxxxxxxxxxxxxx> --- Incremental.c | 11 +++++++++++ mdadm.h | 3 +++ super-ddf.c | 1 + super-intel.c | 32 +++++++++++++++++++++++++++++++- 4 files changed, 46 insertions(+), 1 deletion(-) diff --git a/Incremental.c b/Incremental.c index 6cbc164a27b9..5477a5369c6f 100644 --- a/Incremental.c +++ b/Incremental.c @@ -1467,6 +1467,17 @@ static int Incremental_container(struct supertype *st, char *devname, st->ss->getinfo_super(st, &info, NULL); + if ((c->runstop > 0 && info.container_enough >= 0) || + info.container_enough > 0) + /* pass */; + else { + if (c->export) { + printf("MD_STARTED=no\n"); + } else if (c->verbose) + pr_err("not enough devices to start the container\n"); + return 0; + } + match = conf_match(st, &info, devname, c->verbose, &rv); if (match == NULL && rv == 2) return rv; diff --git a/mdadm.h b/mdadm.h index 709b6104c401..0b647085fea1 100644 --- a/mdadm.h +++ b/mdadm.h @@ -377,6 +377,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[32]; struct mdinfo *devs; struct mdinfo *next; diff --git a/super-ddf.c b/super-ddf.c index a87e3169d325..7571e3b740c6 100644 --- a/super-ddf.c +++ b/super-ddf.c @@ -1975,6 +1975,7 @@ static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info, char *m info->array.ctime = DECADE + __be32_to_cpu(*cptr); info->array.chunk_size = 0; + info->container_enough = 1; info->disk.major = 0; info->disk.minor = 0; diff --git a/super-intel.c b/super-intel.c index 6a664a2e58d3..697820b0d85e 100644 --- a/super-intel.c +++ b/super-intel.c @@ -3778,6 +3778,7 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char * struct intel_super *super = st->sb; struct imsm_disk *disk; int map_disks = info->array.raid_disks; + int max_enough = -1; int i; struct imsm_super *mpb; @@ -3819,9 +3820,12 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char * for (i = 0; i < mpb->num_raid_devs; i++) { struct imsm_dev *dev = get_imsm_dev(super, i); - int j = 0; + int failed, enough, j, missing = 0; struct imsm_map *map; + __u8 state; + failed = imsm_count_failed(super, dev, MAP_0); + state = imsm_check_degraded(super, dev, failed, MAP_0); map = get_imsm_map(dev, MAP_0); /* any newly missing disks? @@ -3836,10 +3840,36 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char * 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; + if (is_gen_migration(dev) && missing) { + /* during general migration we need all disks + * that process is running on. + * No new missing disk is allowed. + */ + max_enough = -1; + enough = -1; + /* no more checks necessary + */ + break; + } + /* in the missing/failed disk case check to see + * if at least one array is runnable + */ + max_enough = max(max_enough, enough); } + dprintf("enough: %d\n", max_enough); + info->container_enough = max_enough; if (super->disks) { __u32 reserved = imsm_reserved_sectors(super, super->disks); -- 2.35.3