From a5d85af748aafe3e3830b9d16faa5c92e783b171 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 22 Nov 2010 19:35:25 +1100 Subject: [PATCH] get_info_super: report which other devices are thought to be working/failed. To accurately detect when an array has been split and is now being recombined, we need to track which other devices each thinks is working. We should never include a device in an array if it thinks that the primary device has failed. This patch just allows get_info_super to return a list of devices and whether they are thought to be working or not. Signed-off-by: NeilBrown --- Assemble.c | 12 ++++++------ Create.c | 8 ++++---- Detail.c | 2 +- Examine.c | 4 ++-- Grow.c | 6 +++--- Incremental.c | 16 ++++++++-------- Manage.c | 4 ++-- Query.c | 2 +- managemon.c | 2 +- mapfile.c | 2 +- mdadm.h | 6 +++++- super-ddf.c | 43 +++++++++++++++++++++++++++++++++--------- super-gpt.c | 2 +- super-intel.c | 52 +++++++++++++++++++++++++++++++++++++-------------- super-mbr.c | 2 +- super0.c | 9 +++++++-- super1.c | 13 ++++++++++--- util.c | 4 ++-- 18 files changed, 127 insertions(+), 62 deletions(-) diff --git a/Assemble.c b/Assemble.c index a25fdbe1..0900f26a 100644 --- a/Assemble.c +++ b/Assemble.c @@ -283,7 +283,7 @@ int Assemble(struct supertype *st, char *mddev, } else { content = &info; memset(content, 0, sizeof(*content)); - tst->ss->getinfo_super(tst, content); + tst->ss->getinfo_super(tst, content, NULL); } if (dfd >= 0) close(dfd); @@ -520,7 +520,7 @@ int Assemble(struct supertype *st, char *mddev, /* Now need to open the array device. Use create_mddev */ if (content == &info) - st->ss->getinfo_super(st, content); + st->ss->getinfo_super(st, content, NULL); trustworthy = FOREIGN; name = content->name; @@ -643,7 +643,7 @@ int Assemble(struct supertype *st, char *mddev, close(mdfd); return 1; } - tst->ss->getinfo_super(tst, content); + tst->ss->getinfo_super(tst, content, NULL); memcpy(content->uuid, ident->uuid, 16); strcpy(content->name, ident->name); @@ -704,7 +704,7 @@ int Assemble(struct supertype *st, char *mddev, close(mdfd); return 1; } - tst->ss->getinfo_super(tst, content); + tst->ss->getinfo_super(tst, content, NULL); tst->ss->free_super(tst); close(dfd); } @@ -798,7 +798,7 @@ int Assemble(struct supertype *st, char *mddev, if (update && strcmp(update, "byteorder")==0) st->minor_version = 90; - st->ss->getinfo_super(st, content); + st->ss->getinfo_super(st, content, NULL); clean = content->array.state & 1; /* now we have some devices that might be suitable. @@ -955,7 +955,7 @@ int Assemble(struct supertype *st, char *mddev, close(mdfd); return 1; } - st->ss->getinfo_super(st, content); + st->ss->getinfo_super(st, content, NULL); #ifndef MDASSEMBLE sysfs_init(content, mdfd, 0); #endif diff --git a/Create.c b/Create.c index 2bf7ebe2..bbf2f2b0 100644 --- a/Create.c +++ b/Create.c @@ -614,7 +614,7 @@ int Create(struct supertype *st, char *mddev, total_slots = info.array.nr_disks; sysfs_init(&info, mdfd, 0); - st->ss->getinfo_super(st, &info); + st->ss->getinfo_super(st, &info, NULL); if (did_default && verbose >= 0) { if (is_subarray(info.text_version)) { @@ -797,7 +797,7 @@ int Create(struct supertype *st, char *mddev, ioctl(mdfd, STOP_ARRAY, NULL); goto abort; } - st->ss->getinfo_super(st, inf); + st->ss->getinfo_super(st, inf, NULL); safe_mode_delay = inf->safe_mode_delay; if (have_container && verbose > 0) @@ -842,7 +842,7 @@ int Create(struct supertype *st, char *mddev, * again returns container info. */ map_lock(&map); - st->ss->getinfo_super(st, &info_new); + st->ss->getinfo_super(st, &info_new, NULL); if (st->ss->external && level != LEVEL_CONTAINER && !same_uuid(info_new.uuid, info.uuid, 0)) { map_update(&map, fd2devnum(mdfd), @@ -857,7 +857,7 @@ int Create(struct supertype *st, char *mddev, if (me) { char *path = strdup(me->path); - st->ss->getinfo_super(st, &info_new); + st->ss->getinfo_super(st, &info_new, NULL); map_update(&map, st->container_dev, info_new.text_version, info_new.uuid, path); diff --git a/Detail.c b/Detail.c index fdfffb72..eb51a3ec 100644 --- a/Detail.c +++ b/Detail.c @@ -143,7 +143,7 @@ int Detail(char *dev, int brief, int export, int test, char *homehost) close(fd2); if (err) continue; - st->ss->getinfo_super(st, &info); + st->ss->getinfo_super(st, &info, NULL); if (array.raid_disks != 0 && /* container */ (info.array.ctime != array.ctime || diff --git a/Examine.c b/Examine.c index 01838c8b..f646805b 100644 --- a/Examine.c +++ b/Examine.c @@ -119,9 +119,9 @@ int Examine(mddev_dev_t devlist, int brief, int export, int scan, ap->spares = 0; ap->st = st; arrays = ap; - st->ss->getinfo_super(st, &ap->info); + st->ss->getinfo_super(st, &ap->info, NULL); } else - st->ss->getinfo_super(st, &ap->info); + st->ss->getinfo_super(st, &ap->info, NULL); if (!st->loaded_container && !(ap->info.disk.state & (1<spares++; diff --git a/Grow.c b/Grow.c index 0571f5b0..800dbb55 100644 --- a/Grow.c +++ b/Grow.c @@ -1728,7 +1728,7 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist, int cnt if (st->ss->load_super(st, fd, NULL)) continue; - st->ss->getinfo_super(st, &dinfo); + st->ss->getinfo_super(st, &dinfo, NULL); st->ss->free_super(st); if (lseek64(fd, @@ -1846,7 +1846,7 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist, int cnt if (st->ss->load_super(st, fdlist[j], NULL)) /* FIXME should be this be an error */ continue; - st->ss->getinfo_super(st, &dinfo); + st->ss->getinfo_super(st, &dinfo, NULL); st->ss->free_super(st); offsets[j] = dinfo.data_offset * 512; } @@ -1908,7 +1908,7 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist, int cnt if (fdlist[j] < 0) continue; if (st->ss->load_super(st, fdlist[j], NULL)) continue; - st->ss->getinfo_super(st, &dinfo); + st->ss->getinfo_super(st, &dinfo, NULL); dinfo.reshape_progress = info->reshape_progress; st->ss->update_super(st, &dinfo, "_reshape_progress", diff --git a/Incremental.c b/Incremental.c index a60be47a..23f59800 100644 --- a/Incremental.c +++ b/Incremental.c @@ -156,7 +156,7 @@ int Incremental(char *devname, int verbose, int runstop, close (dfd); dfd = -1; memset(&info, 0, sizeof(info)); - st->ss->getinfo_super(st, &info); + st->ss->getinfo_super(st, &info, NULL); /* 3/ Check if there is a match in mdadm.conf */ array_list = conf_get_ident(NULL); @@ -433,7 +433,7 @@ int Incremental(char *devname, int verbose, int runstop, } close(dfd2); memset(&info2, 0, sizeof(info2)); - st2->ss->getinfo_super(st2, &info2); + st2->ss->getinfo_super(st2, &info2, NULL); st2->ss->free_super(st2); if (info.array.level != info2.array.level || memcmp(info.uuid, info2.uuid, 16) != 0 || @@ -623,7 +623,7 @@ static void find_reject(int mdfd, struct supertype *st, struct mdinfo *sra, close(dfd); continue; } - st->ss->getinfo_super(st, &info); + st->ss->getinfo_super(st, &info, NULL); st->ss->free_super(st); close(dfd); @@ -668,7 +668,7 @@ static int count_active(struct supertype *st, int mdfd, char **availp, close(dfd); if (ok != 0) continue; - st->ss->getinfo_super(st, &info); + st->ss->getinfo_super(st, &info, NULL); if (!avail) { avail = malloc(info.array.raid_disks); if (!avail) { @@ -685,7 +685,7 @@ static int count_active(struct supertype *st, int mdfd, char **availp, cnt++; max_events = info.events; avail[info.disk.raid_disk] = 2; - st->ss->getinfo_super(st, bestinfo); + st->ss->getinfo_super(st, bestinfo, NULL); } else if (info.events == max_events) { cnt++; avail[info.disk.raid_disk] = 2; @@ -703,12 +703,12 @@ static int count_active(struct supertype *st, int mdfd, char **availp, if (avail[i]) avail[i]--; avail[info.disk.raid_disk] = 2; - st->ss->getinfo_super(st, bestinfo); + st->ss->getinfo_super(st, bestinfo, NULL); } else { /* info.events much bigger */ cnt = 1; cnt1 = 0; memset(avail, 0, info.disk.raid_disk); max_events = info.events; - st->ss->getinfo_super(st, bestinfo); + st->ss->getinfo_super(st, bestinfo, NULL); } } st->ss->free_super(st); @@ -944,7 +944,7 @@ static int partition_try_spare(char *devname, int *dfdp, struct dev_policy *pol, goto next; } - st2->ss->getinfo_super(st2, &info); + st2->ss->getinfo_super(st2, &info, NULL); if (info.component_size > devsectors) /* This partitioning doesn't fit in the device */ goto next; diff --git a/Manage.c b/Manage.c index acfec750..d9530a48 100644 --- a/Manage.c +++ b/Manage.c @@ -664,7 +664,7 @@ int Manage_subdevs(char *devname, int fd, ; else if (st->sb) { struct mdinfo mdi; - st->ss->getinfo_super(st, &mdi); + st->ss->getinfo_super(st, &mdi, NULL); st->ss->uuid_from_super(st, ouuid); if ((mdi.disk.state & (1<array.level = LEVEL_CONTAINER; /* Need to set data_offset and component_size */ - tst->ss->getinfo_super(tst, &new_mdi); + tst->ss->getinfo_super(tst, &new_mdi, NULL); new_mdi.disk.major = disc.major; new_mdi.disk.minor = disc.minor; new_mdi.recovery_start = 0; diff --git a/Query.c b/Query.c index 8847be7e..f9857d6d 100644 --- a/Query.c +++ b/Query.c @@ -90,7 +90,7 @@ int Query(char *dev) close(fd); if (superror == 0) { /* array might be active... */ - st->ss->getinfo_super(st, &info); + st->ss->getinfo_super(st, &info, NULL); if (st->ss == &super0) { mddev = get_md_name(info.array.md_minor); disc.number = info.disk.number; diff --git a/managemon.c b/managemon.c index bab03979..b6f99252 100644 --- a/managemon.c +++ b/managemon.c @@ -276,7 +276,7 @@ static void add_disk_to_container(struct supertype *st, struct mdinfo *sd) */ st2 = dup_super(st); if (st2->ss->load_super(st2, dfd, NULL) == 0) { - st2->ss->getinfo_super(st, &info); + st2->ss->getinfo_super(st, &info, NULL); if (st->ss->compare_super(st, st2) == 0 && info.disk.raid_disk >= 0) { /* Looks like a good member of array. diff --git a/mapfile.c b/mapfile.c index f334822b..b22772c4 100644 --- a/mapfile.c +++ b/mapfile.c @@ -408,7 +408,7 @@ void RebuildMap(void) close(dfd); if (ok != 0) continue; - st->ss->getinfo_super(st, &info); + st->ss->getinfo_super(st, &info, NULL); if (md->devnum >= 0) path = map_dev(MD_MAJOR, md->devnum, 0); else diff --git a/mdadm.h b/mdadm.h index 577d858e..6f7f06f5 100644 --- a/mdadm.h +++ b/mdadm.h @@ -534,8 +534,12 @@ extern struct superswitch { * The particular device should be: * The last device added by add_to_super * The device the metadata was loaded from by load_super + * If 'map' is present, then it is an array raid_disks long + * (raid_disk must already be set and correct) and it is filled + * with 1 for slots that are thought to be active and 0 for slots which + * appear to be failed/missing. */ - void (*getinfo_super)(struct supertype *st, struct mdinfo *info); + void (*getinfo_super)(struct supertype *st, struct mdinfo *info, char *map); /* Check if the given metadata is flagged as belonging to "this" * host. 0 for 'no', 1 for 'yes', -1 for "Don't record homehost" diff --git a/super-ddf.c b/super-ddf.c index fca8edd7..e492b4e5 100644 --- a/super-ddf.c +++ b/super-ddf.c @@ -1187,7 +1187,7 @@ static void examine_super_ddf(struct supertype *st, char *homehost) examine_pds(sb); } -static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info); +static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info, char *map); static void uuid_from_super_ddf(struct supertype *st, int uuid[4]); @@ -1197,7 +1197,7 @@ static void brief_examine_super_ddf(struct supertype *st, int verbose) */ struct mdinfo info; char nbuf[64]; - getinfo_super_ddf(st, &info); + getinfo_super_ddf(st, &info, NULL); fname_from_uuid(st, &info, nbuf, ':'); printf("ARRAY metadata=ddf UUID=%s\n", nbuf + 5); @@ -1211,7 +1211,7 @@ static void brief_examine_subarrays_ddf(struct supertype *st, int verbose) struct mdinfo info; unsigned int i; char nbuf[64]; - getinfo_super_ddf(st, &info); + getinfo_super_ddf(st, &info, NULL); fname_from_uuid(st, &info, nbuf, ':'); for (i = 0; i < __be16_to_cpu(ddf->virt->max_vdes); i++) { @@ -1233,7 +1233,7 @@ static void export_examine_super_ddf(struct supertype *st) { struct mdinfo info; char nbuf[64]; - getinfo_super_ddf(st, &info); + getinfo_super_ddf(st, &info, NULL); fname_from_uuid(st, &info, nbuf, ':'); printf("MD_METADATA=ddf\n"); printf("MD_LEVEL=container\n"); @@ -1259,7 +1259,7 @@ static void brief_detail_super_ddf(struct supertype *st) // struct ddf_super *ddf = st->sb; struct mdinfo info; char nbuf[64]; - getinfo_super_ddf(st, &info); + getinfo_super_ddf(st, &info, NULL); fname_from_uuid(st, &info, nbuf,':'); printf(" UUID=%s", nbuf + 5); } @@ -1346,14 +1346,15 @@ static void uuid_from_super_ddf(struct supertype *st, int uuid[4]) memcpy(uuid, buf, 4*4); } -static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info); +static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info, char *map); -static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info) +static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info, char *map) { struct ddf_super *ddf = st->sb; + int map_disks = info->array.raid_disks; if (ddf->currentconf) { - getinfo_super_ddf_bvd(st, info); + getinfo_super_ddf_bvd(st, info, map); return; } @@ -1397,17 +1398,29 @@ static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info) uuid_from_super_ddf(st, info->uuid); + if (map) { + int i; + for (i = 0 ; i < map_disks; i++) { + if (i < info->array.raid_disks && + (__be16_to_cpu(ddf->phys->entries[i].state) & DDF_Online) && + !(__be16_to_cpu(ddf->phys->entries[i].state) & DDF_Failed)) + map[i] = 1; + else + map[i] = 0; + } + } } static int rlq_to_layout(int rlq, int prl, int raiddisks); -static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info) +static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info, char *map) { struct ddf_super *ddf = st->sb; struct vcl *vc = ddf->currentconf; int cd = ddf->currentdev; int j; struct dl *dl; + int map_disks = info->array.raid_disks; /* FIXME this returns BVD info - what if we want SVD ?? */ @@ -1470,6 +1483,18 @@ static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info) for(j=0; j<16; j++) if (info->name[j] == ' ') info->name[j] = 0; + + if (map) + for (j = 0; j < map_disks; j++) { + map[j] = 0; + if (j < info->array.raid_disks) { + int i = find_phys(ddf, vc->conf.phys_refnum[j]); + if (i >= 0 && + (__be16_to_cpu(ddf->phys->entries[i].state) & DDF_Online) && + !(__be16_to_cpu(ddf->phys->entries[i].state) & DDF_Failed)) + map[i] = 1; + } + } } diff --git a/super-gpt.c b/super-gpt.c index 982b4e9b..116e5686 100644 --- a/super-gpt.c +++ b/super-gpt.c @@ -156,7 +156,7 @@ static int store_gpt(struct supertype *st, int fd) return 0; } -static void getinfo_gpt(struct supertype *st, struct mdinfo *info) +static void getinfo_gpt(struct supertype *st, struct mdinfo *info, char *map) { struct GPT *gpt = st->sb + 512; struct GPT_part_entry *gpe = st->sb + 1024; diff --git a/super-intel.c b/super-intel.c index 38d0ae30..156585c4 100644 --- a/super-intel.c +++ b/super-intel.c @@ -741,7 +741,7 @@ static void print_imsm_disk(struct imsm_super *mpb, int index, __u32 reserved) human_size(sz * 512)); } -static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info); +static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *map); static void examine_super_imsm(struct supertype *st, char *homehost) { @@ -762,7 +762,7 @@ static void examine_super_imsm(struct supertype *st, char *homehost) printf(" Orig Family : %08x\n", __le32_to_cpu(mpb->orig_family_num)); printf(" Family : %08x\n", __le32_to_cpu(mpb->family_num)); printf(" Generation : %08x\n", __le32_to_cpu(mpb->generation_num)); - getinfo_super_imsm(st, &info); + getinfo_super_imsm(st, &info, NULL); fname_from_uuid(st, &info, nbuf, ':'); printf(" UUID : %s\n", nbuf + 5); sum = __le32_to_cpu(mpb->check_sum); @@ -789,7 +789,7 @@ static void examine_super_imsm(struct supertype *st, char *homehost) struct imsm_dev *dev = __get_imsm_dev(mpb, i); super->current_vol = i; - getinfo_super_imsm(st, &info); + getinfo_super_imsm(st, &info, NULL); fname_from_uuid(st, &info, nbuf, ':'); print_imsm_dev(dev, nbuf + 5, super->disks->index); } @@ -812,7 +812,7 @@ static void brief_examine_super_imsm(struct supertype *st, int verbose) return; } - getinfo_super_imsm(st, &info); + getinfo_super_imsm(st, &info, NULL); fname_from_uuid(st, &info, nbuf, ':'); printf("ARRAY metadata=imsm UUID=%s\n", nbuf + 5); } @@ -829,13 +829,13 @@ static void brief_examine_subarrays_imsm(struct supertype *st, int verbose) if (!super->anchor->num_raid_devs) return; - getinfo_super_imsm(st, &info); + getinfo_super_imsm(st, &info, NULL); fname_from_uuid(st, &info, nbuf, ':'); for (i = 0; i < super->anchor->num_raid_devs; i++) { struct imsm_dev *dev = get_imsm_dev(super, i); super->current_vol = i; - getinfo_super_imsm(st, &info); + getinfo_super_imsm(st, &info, NULL); fname_from_uuid(st, &info, nbuf1, ':'); printf("ARRAY /dev/md/%.16s container=%s member=%d UUID=%s\n", dev->volume, nbuf + 5, i, nbuf1 + 5); @@ -849,7 +849,7 @@ static void export_examine_super_imsm(struct supertype *st) struct mdinfo info; char nbuf[64]; - getinfo_super_imsm(st, &info); + getinfo_super_imsm(st, &info, NULL); fname_from_uuid(st, &info, nbuf, ':'); printf("MD_METADATA=imsm\n"); printf("MD_LEVEL=container\n"); @@ -862,7 +862,7 @@ static void detail_super_imsm(struct supertype *st, char *homehost) struct mdinfo info; char nbuf[64]; - getinfo_super_imsm(st, &info); + getinfo_super_imsm(st, &info, NULL); fname_from_uuid(st, &info, nbuf, ':'); printf("\n UUID : %s\n", nbuf + 5); } @@ -871,7 +871,7 @@ static void brief_detail_super_imsm(struct supertype *st) { struct mdinfo info; char nbuf[64]; - getinfo_super_imsm(st, &info); + getinfo_super_imsm(st, &info, NULL); fname_from_uuid(st, &info, nbuf, ':'); printf(" UUID=%s", nbuf + 5); } @@ -1434,13 +1434,14 @@ static int imsm_level_to_layout(int level) return UnSet; } -static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info) +static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info, char *dmap) { struct intel_super *super = st->sb; struct imsm_dev *dev = get_imsm_dev(super, super->current_vol); struct imsm_map *map = get_imsm_map(dev, 0); struct dl *dl; char *devname; + int map_disks = info->array.raid_disks; for (dl = super->disks; dl; dl = dl->next) if (dl->raiddisk == info->disk.raid_disk) @@ -1512,7 +1513,21 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info) free(devname); info->safe_mode_delay = 4000; /* 4 secs like the Matrix driver */ uuid_from_super_imsm(st, info->uuid); -} + + if (dmap) { + int i, j; + for (i=0; iarray.raid_disks) { + struct imsm_disk *dsk; + j = get_imsm_disk_idx(dev, i); + dsk = get_imsm_disk(super, j); + if (dsk && (dsk->status & CONFIGURED_DISK)) + dmap[i] = 1; + } + } + } +} /* check the config file to see if we can return a real uuid for this spare */ static void fixup_container_spare_uuid(struct mdinfo *inf) @@ -1559,13 +1574,14 @@ static struct imsm_disk *get_imsm_missing(struct intel_super *super, __u8 index) return NULL; } -static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info) +static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *map) { struct intel_super *super = st->sb; struct imsm_disk *disk; + int map_disks = info->array.raid_disks; if (super->current_vol >= 0) { - getinfo_super_imsm_volume(st, info); + getinfo_super_imsm_volume(st, info, map); return; } @@ -1664,6 +1680,14 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info) memcpy(info->uuid, uuid_match_any, sizeof(int[4])); fixup_container_spare_uuid(info); } + + /* I don't know how to compute 'map' on imsm, so use safe default */ + if (map) { + int i; + for (i = 0; i < map_disks; i++) + map[i] = 1; + } + } static int update_super_imsm(struct supertype *st, struct mdinfo *info, @@ -4353,7 +4377,7 @@ static struct mdinfo *container_content_imsm(struct supertype *st) this->next = rest; super->current_vol = i; - getinfo_super_imsm_volume(st, this); + getinfo_super_imsm_volume(st, this, NULL); for (slot = 0 ; slot < map->num_members; slot++) { unsigned long long recovery_start; struct mdinfo *info_d; diff --git a/super-mbr.c b/super-mbr.c index 811ad1dc..0751e17c 100644 --- a/super-mbr.c +++ b/super-mbr.c @@ -148,7 +148,7 @@ static int store_mbr(struct supertype *st, int fd) return 0; } -static void getinfo_mbr(struct supertype *st, struct mdinfo *info) +static void getinfo_mbr(struct supertype *st, struct mdinfo *info, char *map) { struct MBR *sb = st->sb; int i; diff --git a/super0.c b/super0.c index a650c3e6..b9d149eb 100644 --- a/super0.c +++ b/super0.c @@ -339,11 +339,12 @@ static void uuid_from_super0(struct supertype *st, int uuid[4]) } } -static void getinfo_super0(struct supertype *st, struct mdinfo *info) +static void getinfo_super0(struct supertype *st, struct mdinfo *info, char *map) { mdp_super_t *sb = st->sb; int working = 0; int i; + int map_disks = info->array.raid_disks; info->array.major_version = sb->major_version; info->array.minor_version = sb->minor_version; @@ -391,8 +392,12 @@ static void getinfo_super0(struct supertype *st, struct mdinfo *info) if ((sb->disks[i].state & (1<disks[i].raid_disk < (unsigned)info->array.raid_disks) && (sb->disks[i].state & (1<disks[i].state & (1<disks[i].state & (1<array.working_disks = working; } diff --git a/super1.c b/super1.c index 24c18c0e..a52df645 100644 --- a/super1.c +++ b/super1.c @@ -558,12 +558,13 @@ static void uuid_from_super1(struct supertype *st, int uuid[4]) cuuid[i] = super->set_uuid[i]; } -static void getinfo_super1(struct supertype *st, struct mdinfo *info) +static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map) { struct mdp_superblock_1 *sb = st->sb; int working = 0; unsigned int i; - int role; + unsigned int role; + unsigned int map_disks = info->array.raid_disks; info->array.major_version = 1; info->array.minor_version = st->minor_version; @@ -629,10 +630,16 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info) } else info->reshape_active = 0; + if (map) + for (i=0; imax_dev); i++) { role = __le16_to_cpu(sb->dev_roles[i]); - if (/*role == 0xFFFF || */role < info->array.raid_disks) + if (/*role == 0xFFFF || */role < (unsigned) info->array.raid_disks) { working++; + if (map && role < map_disks) + map[role] = 1; + } } info->array.working_disks = working; diff --git a/util.c b/util.c index c9976218..27989636 100644 --- a/util.c +++ b/util.c @@ -500,7 +500,7 @@ int check_raid(int fd, char *name) /* Looks like a raid array .. */ fprintf(stderr, Name ": %s appears to be part of a raid array:\n", name); - st->ss->getinfo_super(st, &info); + st->ss->getinfo_super(st, &info, NULL); st->ss->free_super(st); crtime = info.array.ctime; level = map_num(pers, info.array.level); @@ -1140,7 +1140,7 @@ struct supertype *guess_super_type(int fd, enum guess_types guess_type) rv = ss->load_super(st, fd, NULL); if (rv == 0) { struct mdinfo info; - st->ss->getinfo_super(st, &info); + st->ss->getinfo_super(st, &info, NULL); if (bestsuper == -1 || besttime < info.array.ctime) { bestsuper = i; -- 2.39.2