]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
conditionally update uuids in the map file after Create()
authorDan Williams <dan.j.williams@intel.com>
Sat, 1 Aug 2009 00:11:41 +0000 (17:11 -0700)
committerDan Williams <dan.j.williams@intel.com>
Sat, 1 Aug 2009 00:11:41 +0000 (17:11 -0700)
The map file needs to be updated after adding the first member array to
an Intel metadata container.  The uuid for an imsm container uses the
->family_num field of the metadata.  This field is static, but is only
set after the first member array has been created.  Prior to this all
devices are free floating spares and do not have any information that
can identify specific container membership.  At Create() time we take
the uninitialized uuid from ->get_info_super() prior to updating the
metadata.  So the current result is:

# mdadm --create /dev/md/imsm /dev/sd[b-e] -n 4 -e imsm
# mdadm --create /dev/md/vol0 /dev/md/imsm -n 4 -l 0
# cat /var/run/mdadm/map
md126 /md127/0 3e03aee2:78c3c593:1e8ecaf0:eefb53ed /dev/md/vol0
md127 imsm 53d6f8b1:7a783f24:f30483c5:705c48c7 /dev/md/imsm
# mdadm -Ebs
ARRAY metadata=imsm UUID=589d2d2c:4221a54d:acb63c06:c3907f52
ARRAY /dev/md/vol0 container=589d2d2c:4221a54d:acb63c06:c3907f52
member=0 UUID=57b89b63:5cd0eae1:17dd26b3:51cc78d4

So, before we write out the new metadata check to see if the member
array uuid has changed as a result of this addition.  If it has, update
its uuid in the map file and flag its parent container for updating.  In
support of updating the container uuid the semantics of
->write_init_super are changed to clear any metadata specific member
array cursors (e.g. ddf_super.currentconf or intel_super.current_vol)
such that a subsequent call to ->getinfo_super returns container
information.

Reported-by: Ignacy Kasperowicz <ignacy.kasperowicz@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Create.c
super-ddf.c
super-intel.c

index 8a73799c4448c727308228dc51c34049093ebe65..c96b31950bc95c5c119e2de95906dddd1e726c5c 100644 (file)
--- a/Create.c
+++ b/Create.c
@@ -792,7 +792,39 @@ int Create(struct supertype *st, char *mddev,
                            dv == moved_disk && dnum != insert_point) break;
                }
                if (pass == 1) {
+                       struct mdinfo info_new;
+                       struct map_ent *me = NULL;
+
+                       /* check to see if the uuid has changed due to these
+                        * metadata changes, and if so update the member array
+                        * and container uuid.  Note ->write_init_super clears
+                        * the subarray cursor such that ->getinfo_super once
+                        * again returns container info.
+                        */
+                       map_lock(&map);
+                       st->ss->getinfo_super(st, &info_new);
+                       if (st->ss->external && level != LEVEL_CONTAINER &&
+                           !same_uuid(info_new.uuid, info.uuid, 0)) {
+                               map_update(&map, fd2devnum(mdfd),
+                                          info_new.text_version,
+                                          info_new.uuid, chosen_name);
+                               me = map_by_devnum(&map, st->container_dev);
+                       }
+
                        st->ss->write_init_super(st);
+
+                       /* update parent container uuid */
+                       if (me) {
+                               char *path = strdup(me->path);
+
+                               st->ss->getinfo_super(st, &info_new);
+                               map_update(&map, st->container_dev,
+                                          info_new.text_version,
+                                          info_new.uuid, path);
+                               free(path);
+                       }
+                       map_unlock(&map);
+
                        flush_metadata_updates(st);
                }
        }
index 8153924e16fd33d001f96dc91e3135b65e06fbdf..0b1527591029808e445cd58176607174b6dbd8e2 100644 (file)
@@ -2362,15 +2362,19 @@ static int __write_init_super_ddf(struct supertype *st, int do_close)
 
 static int write_init_super_ddf(struct supertype *st)
 {
+       struct ddf_super *ddf = st->sb;
+       struct vcl *currentconf = ddf->currentconf;
+
+       /* we are done with currentconf reset it to point st at the container */
+       ddf->currentconf = NULL;
 
        if (st->update_tail) {
                /* queue the virtual_disk and vd_config as metadata updates */
                struct virtual_disk *vd;
                struct vd_config *vc;
-               struct ddf_super *ddf = st->sb;
                int len;
 
-               if (!ddf->currentconf) {
+               if (!currentconf) {
                        int len = (sizeof(struct phys_disk) +
                                   sizeof(struct phys_disk_entry));
 
@@ -2389,14 +2393,14 @@ static int write_init_super_ddf(struct supertype *st)
                len = sizeof(struct virtual_disk) + sizeof(struct virtual_entry);
                vd = malloc(len);
                *vd = *ddf->virt;
-               vd->entries[0] = ddf->virt->entries[ddf->currentconf->vcnum];
-               vd->populated_vdes = __cpu_to_be16(ddf->currentconf->vcnum);
+               vd->entries[0] = ddf->virt->entries[currentconf->vcnum];
+               vd->populated_vdes = __cpu_to_be16(currentconf->vcnum);
                append_metadata_update(st, vd, len);
 
                /* Then the vd_config */
                len = ddf->conf_rec_len * 512;
                vc = malloc(len);
-               memcpy(vc, &ddf->currentconf->conf, len);
+               memcpy(vc, &currentconf->conf, len);
                append_metadata_update(st, vc, len);
 
                /* FIXME I need to close the fds! */
index 207d3be952fa78f8bf4c26332812b3d73a912a63..56947ded9db8db4af370a7002dd79c62f6e70ad5 100644 (file)
@@ -2724,17 +2724,16 @@ static int write_super_imsm(struct intel_super *super, int doclose)
 }
 
 
-static int create_array(struct supertype *st)
+static int create_array(struct supertype *st, int dev_idx)
 {
        size_t len;
        struct imsm_update_create_array *u;
        struct intel_super *super = st->sb;
-       struct imsm_dev *dev = get_imsm_dev(super, super->current_vol);
+       struct imsm_dev *dev = get_imsm_dev(super, dev_idx);
        struct imsm_map *map = get_imsm_map(dev, 0);
        struct disk_info *inf;
        struct imsm_disk *disk;
        int i;
-       int idx;
 
        len = sizeof(*u) - sizeof(*dev) + sizeof_imsm_dev(dev, 0) +
              sizeof(*inf) * map->num_members;
@@ -2746,11 +2745,12 @@ static int create_array(struct supertype *st)
        }
 
        u->type = update_create_array;
-       u->dev_idx = super->current_vol;
+       u->dev_idx = dev_idx;
        imsm_copy_dev(&u->dev, dev);
        inf = get_disk_info(u);
        for (i = 0; i < map->num_members; i++) {
-               idx = get_imsm_disk_idx(dev, i);
+               int idx = get_imsm_disk_idx(dev, i);
+
                disk = get_imsm_disk(super, idx);
                serialcpy(inf[i].serial, disk->serial);
        }
@@ -2784,21 +2784,26 @@ static int _add_disk(struct supertype *st)
 
 static int write_init_super_imsm(struct supertype *st)
 {
+       struct intel_super *super = st->sb;
+       int current_vol = super->current_vol;
+
+       /* we are done with current_vol reset it to point st at the container */
+       super->current_vol = -1;
+
        if (st->update_tail) {
                /* queue the recently created array / added disk
                 * as a metadata update */
-               struct intel_super *super = st->sb;
                struct dl *d;
                int rv;
 
                /* determine if we are creating a volume or adding a disk */
-               if (super->current_vol < 0) {
+               if (current_vol < 0) {
                        /* in the add disk case we are running in mdmon
                         * context, so don't close fd's
                         */
                        return _add_disk(st);
                } else
-                       rv = create_array(st);
+                       rv = create_array(st, current_vol);
 
                for (d = super->disks; d ; d = d->next) {
                        close(d->fd);