]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super-intel.c
Use load_container in Incremental assembly.
[thirdparty/mdadm.git] / super-intel.c
index 38d0ae30550005d7e27fe375b8f622f18af28eb5..430c5edf61c16115c0ec622bd699be7f31a7a771 100644 (file)
@@ -333,6 +333,7 @@ static struct supertype *match_metadata_desc_imsm(char *arg)
        if (!st)
                return NULL;
        memset(st, 0, sizeof(*st));
+       st->container_dev = NoMdDev;
        st->ss = &super_imsm;
        st->max_devs = IMSM_MAX_DEVICES;
        st->minor_version = 0;
@@ -741,7 +742,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 +763,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 +790,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 +813,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 +830,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 +850,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 +863,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 +872,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 +1435,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 +1514,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 +1575,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 +1681,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,
@@ -2760,7 +2785,7 @@ imsm_thunderdome(struct intel_super **super_list, int len)
 }
 
 static int load_super_imsm_all(struct supertype *st, int fd, void **sbp,
-                              char *devname, int keep_fd)
+                              char *devname)
 {
        struct mdinfo *sra;
        struct intel_super *super_list = NULL;
@@ -2796,22 +2821,20 @@ static int load_super_imsm_all(struct supertype *st, int fd, void **sbp,
 
                err = 2;
                sprintf(nm, "%d:%d", sd->disk.major, sd->disk.minor);
-               dfd = dev_open(nm, keep_fd ? O_RDWR : O_RDONLY);
+               dfd = dev_open(nm, O_RDWR);
                if (dfd < 0)
                        goto error;
 
-               err = load_and_parse_mpb(dfd, s, NULL, keep_fd);
+               err = load_and_parse_mpb(dfd, s, NULL, 1);
 
                /* retry the load if we might have raced against mdmon */
                if (err == 3 && mdmon_running(devnum))
                        for (retry = 0; retry < 3; retry++) {
                                usleep(3000);
-                               err = load_and_parse_mpb(dfd, s, NULL, keep_fd);
+                               err = load_and_parse_mpb(dfd, s, NULL, 1);
                                if (err != 3)
                                        break;
                        }
-               if (!keep_fd)
-                       close(dfd);
                if (err)
                        goto error;
        }
@@ -2828,25 +2851,6 @@ static int load_super_imsm_all(struct supertype *st, int fd, void **sbp,
                err = 2;
                goto error;
        }
-
-       if (st->subarray[0]) {
-               unsigned long val;
-               char *ep;
-
-               err = 1;
-               val = strtoul(st->subarray, &ep, 10);
-               if (*ep != '\0') {
-                       free_imsm(super);
-                       goto error;
-               }
-
-               if (val < super->anchor->num_raid_devs)
-                       super->current_vol = val;
-               else {
-                       free_imsm(super);
-                       goto error;
-               }
-       }
        err = 0;
 
  error:
@@ -2872,6 +2876,11 @@ static int load_super_imsm_all(struct supertype *st, int fd, void **sbp,
 
        return 0;
 }
+
+static int load_container_imsm(struct supertype *st, int fd, char *devname)
+{
+       return load_super_imsm_all(st, fd, &st->sb, devname);
+}
 #endif
 
 static int load_super_imsm(struct supertype *st, int fd, char *devname)
@@ -2880,7 +2889,7 @@ static int load_super_imsm(struct supertype *st, int fd, char *devname)
        int rv;
 
 #ifndef MDASSEMBLE
-       if (load_super_imsm_all(st, fd, &st->sb, devname, 1) == 0)
+       if (load_super_imsm_all(st, fd, &st->sb, devname) == 0)
                return 0;
 #endif
 
@@ -2909,24 +2918,6 @@ static int load_super_imsm(struct supertype *st, int fd, char *devname)
                return rv;
        }
 
-       if (st->subarray[0]) {
-               unsigned long val;
-               char *ep;
-
-               val = strtoul(st->subarray, &ep, 10);
-               if (*ep != '\0') {
-                       free_imsm(super);
-                       return 1;
-               }
-
-               if (val < super->anchor->num_raid_devs)
-                       super->current_vol = val;
-               else {
-                       free_imsm(super);
-                       return 1;
-               }
-       }
-
        st->sb = super;
        if (st->ss == NULL) {
                st->ss = &super_imsm;
@@ -3087,7 +3078,6 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
 
        if (!check_name(super, name, 0))
                return 0;
-       sprintf(st->subarray, "%d", idx);
        dv = malloc(sizeof(*dv));
        if (!dv) {
                fprintf(stderr, Name ": failed to allocate device list entry\n");
@@ -4101,7 +4091,7 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout,
                 */
                struct intel_super *super;
 
-               if (load_super_imsm_all(st, cfd, (void **) &super, NULL, 1) == 0) {
+               if (load_super_imsm_all(st, cfd, (void **) &super, NULL) == 0) {
                        st->sb = super;
                        st->container_dev = fd2devnum(cfd);
                        close(cfd);
@@ -4205,19 +4195,19 @@ static int kill_subarray_imsm(struct supertype *st)
        return 0;
 }
 
-static int update_subarray_imsm(struct supertype *st, char *update, mddev_ident_t ident)
+static int update_subarray_imsm(struct supertype *st, char *subarray,
+                               char *update, mddev_ident_t ident)
 {
        /* update the subarray currently referenced by ->current_vol */
        struct intel_super *super = st->sb;
        struct imsm_super *mpb = super->anchor;
 
-       if (super->current_vol < 0)
-               return 2;
-
        if (strcmp(update, "name") == 0) {
                char *name = ident->name;
+               char *ep;
+               int vol;
 
-               if (is_subarray_active(st->subarray, st->devname)) {
+               if (is_subarray_active(subarray, st->devname)) {
                        fprintf(stderr,
                                Name ": Unable to update name of active subarray\n");
                        return 2;
@@ -4226,20 +4216,24 @@ static int update_subarray_imsm(struct supertype *st, char *update, mddev_ident_
                if (!check_name(super, name, 0))
                        return 2;
 
+               vol = strtoul(subarray, &ep, 10);
+               if (*ep != '\0' || vol >= super->anchor->num_raid_devs)
+                       return 2;
+
                if (st->update_tail) {
                        struct imsm_update_rename_array *u = malloc(sizeof(*u));
 
                        if (!u)
                                return 2;
                        u->type = update_rename_array;
-                       u->dev_idx = super->current_vol;
+                       u->dev_idx = vol;
                        snprintf((char *) u->name, MAX_RAID_SERIAL_LEN, "%s", name);
                        append_metadata_update(st, u, sizeof(*u));
                } else {
                        struct imsm_dev *dev;
                        int i;
 
-                       dev = get_imsm_dev(super, super->current_vol);
+                       dev = get_imsm_dev(super, vol);
                        snprintf((char *) dev->volume, MAX_RAID_SERIAL_LEN, "%s", name);
                        for (i = 0; i < mpb->num_raid_devs; i++) {
                                dev = get_imsm_dev(super, i);
@@ -4303,11 +4297,12 @@ static void update_recovery_start(struct imsm_dev *dev, struct mdinfo *array)
 }
 
 
-static struct mdinfo *container_content_imsm(struct supertype *st)
+static struct mdinfo *container_content_imsm(struct supertype *st, char *subarray)
 {
        /* Given a container loaded by load_super_imsm_all,
         * extract information about all the arrays into
         * an mdinfo tree.
+        * If 'subarray' is given, just extract info about that array.
         *
         * For each imsm_dev create an mdinfo, fill it in,
         *  then look for matching devices in super->disks
@@ -4316,7 +4311,7 @@ static struct mdinfo *container_content_imsm(struct supertype *st)
        struct intel_super *super = st->sb;
        struct imsm_super *mpb = super->anchor;
        struct mdinfo *rest = NULL;
-       int i;
+       unsigned int i;
 
        /* do not assemble arrays that might have bad blocks */
        if (imsm_bbm_log_size(super->anchor)) {
@@ -4326,10 +4321,18 @@ static struct mdinfo *container_content_imsm(struct supertype *st)
        }
 
        for (i = 0; i < mpb->num_raid_devs; i++) {
-               struct imsm_dev *dev = get_imsm_dev(super, i);
-               struct imsm_map *map = get_imsm_map(dev, 0);
+               struct imsm_dev *dev;
+               struct imsm_map *map;
                struct mdinfo *this;
                int slot;
+               char *ep;
+
+               if (subarray &&
+                   (i != strtoul(subarray, &ep, 10) || *ep != '\0'))
+                       continue;
+
+               dev = get_imsm_dev(super, i);
+               map = get_imsm_map(dev, 0);
 
                /* do not publish arrays that are in the middle of an
                 * unsupported migration
@@ -4353,7 +4356,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;
@@ -5576,6 +5579,7 @@ struct superswitch super_imsm = {
        .detail_platform = detail_platform_imsm,
        .kill_subarray = kill_subarray_imsm,
        .update_subarray = update_subarray_imsm,
+       .load_container = load_container_imsm,
 #endif
        .match_home     = match_home_imsm,
        .uuid_from_super= uuid_from_super_imsm,