]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
get_info_super: report which other devices are thought to be working/failed.
authorNeilBrown <neilb@suse.de>
Mon, 22 Nov 2010 08:35:25 +0000 (19:35 +1100)
committerNeilBrown <neilb@suse.de>
Mon, 22 Nov 2010 08:35:25 +0000 (19:35 +1100)
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 <neilb@suse.de>
18 files changed:
Assemble.c
Create.c
Detail.c
Examine.c
Grow.c
Incremental.c
Manage.c
Query.c
managemon.c
mapfile.c
mdadm.h
super-ddf.c
super-gpt.c
super-intel.c
super-mbr.c
super0.c
super1.c
util.c

index a25fdbe17c50303c01b7ccfba19a1b192b184277..0900f26a16bcab9d87181fc6feab75498c9ca8fb 100644 (file)
@@ -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
index 2bf7ebe2dfac380e2c7abe38ab2c7dce38360d50..bbf2f2b00da25cfdbc44bae532bdf9754ca93baa 100644 (file)
--- 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);
index fdfffb72ec0290e5ed5ada2380fc9310a7990f8c..eb51a3ecee279a328c5c0fb8d42ab00601ece2e9 100644 (file)
--- 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 ||
index 01838c8b48d3307c3350cbd6efe2a1fe73519f67..f646805b911dfd66e087a768c81d934959206a8d 100644 (file)
--- 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<<MD_DISK_SYNC)))
                                ap->spares++;
diff --git a/Grow.c b/Grow.c
index 0571f5b0e16d170e5bb9671d7f62df5f0cefa65c..800dbb55e29138ac8fe4f3e80d220ae6a1ea38aa 100644 (file)
--- 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",
index a60be47a749e8377dace2ed7869fca81270beb66..23f59800d38ecadac827218b963e8c672c816d2c 100644 (file)
@@ -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;
index acfec750f714b28c9570ee408380c58cb0ac8611..d9530a489e34c8f613b1e4ee9533c3ec5cf040a5 100644 (file)
--- 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<<MD_DISK_ACTIVE)) &&
                                            !(mdi.disk.state & (1<<MD_DISK_FAULTY)) &&
@@ -855,7 +855,7 @@ int Manage_subdevs(char *devname, int fd,
                                }
                                sra->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 8847be7ec0b6a1e0880865d672b38f9f0374d2e2..f9857d6d9e2ddadd86726db70046324bf4b0ee7d 100644 (file)
--- 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;
index bab0397921a7d30dc24e012cfa9decc8d5e877f5..b6f99252716ac08120dd5d56050695844c9a413f 100644 (file)
@@ -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.
index f334822bf697783ba01845b7aee814c7fff7989b..b22772c4cf5bf748f1ae824cda23d55325b33202 100644 (file)
--- 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 577d858e49f54a27c421bf4acdab147df52ab95b..6f7f06f5a58ff497c132ffa08de6929fd7d4d16a 100644 (file)
--- 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"
index fca8edd742e472060f0219050731abcf399488a1..e492b4e5c770cb5c733f755cabc497e203eb680b 100644 (file)
@@ -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;
+                       }
+               }
 }
 
 
index 982b4e9b8c33d4b6f309b62face20501953427b2..116e568646fe80ba352841994ba3afcf89103a37 100644 (file)
@@ -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;
index 38d0ae30550005d7e27fe375b8f622f18af28eb5..156585c446b61eeccfc04febb3038d13eeeb1c9f 100644 (file)
@@ -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; i<map_disks; i++) {
+                       dmap[i] = 0;
+                       if (i < info->array.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;
index 811ad1dcb1422c153e5d462c24a0f8995d3e3ea5..0751e17cec965fd9182e8a53613070157bf3f07e 100644 (file)
@@ -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;
index a650c3e69784a05ade30624cfb8955c39c77cb66..b9d149eb6a80c30124311f65fd13b2d67c61055a 100644 (file)
--- 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<<MD_DISK_SYNC)) &&
                    (sb->disks[i].raid_disk < (unsigned)info->array.raid_disks) &&
                    (sb->disks[i].state & (1<<MD_DISK_ACTIVE)) &&
-                   !(sb->disks[i].state & (1<<MD_DISK_FAULTY)))
+                   !(sb->disks[i].state & (1<<MD_DISK_FAULTY))) {
                        working ++;
+                       if (map && i < map_disks)
+                               map[i] = 1;
+               } else if (map && i < map_disks)
+                       map[i] = 0;
        info->array.working_disks = working;
 }
 
index 24c18c0ee3ea57f55eb321db031edd662bf57710..a52df6452b16f5c7e4d44052ddc298ca1b929058 100644 (file)
--- 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; i<map_disks; i++)
+                       map[i] = 0;
        for (i = 0; i < __le32_to_cpu(sb->max_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 c9976218962ab0ddeda0d4ff7ad40ab8c45b8b74..27989636d4ab2318cbe423f2c027c8560a0cb567 100644 (file)
--- 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;