]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super-ddf.c
Make sure resync_start is initialised properly and maintained properly
[thirdparty/mdadm.git] / super-ddf.c
index b16001e9fc1c75c0bbcf0046203364a67f6fef60..5d38750489193302e6a4bcd0e56809ccdc29957b 100644 (file)
 #include "sha1.h"
 #include <values.h>
 
-static inline int ROUND_UP(int a, int base)
-{
-       return ((a+base-1)/base)*base;
-}
-
 /* a non-official T10 name for creation GUIDs */
 static char T10[] = "Linux-MD";
 
@@ -395,8 +390,9 @@ struct bad_block_log {
  * built in Create or Assemble to describe the whole array.
  */
 struct ddf_super {
-       struct ddf_header anchor, primary, secondary, *active;
+       struct ddf_header anchor, primary, secondary;
        struct ddf_controller_data controller;
+       struct ddf_header *active;
        struct phys_disk        *phys;
        struct virtual_disk     *virt;
        int pdsize, vdsize;
@@ -404,22 +400,32 @@ struct ddf_super {
        int currentdev;
        int updates_pending;
        struct vcl {
-               struct vcl      *next;
-               __u64           *lba_offset; /* location in 'conf' of
-                                             * the lba table */
-               int     vcnum; /* index into ->virt */
-               __u64           *block_sizes; /* NULL if all the same */
+               union {
+                       char space[512];
+                       struct {
+                               struct vcl      *next;
+                               __u64           *lba_offset; /* location in 'conf' of
+                                                             * the lba table */
+                               int     vcnum; /* index into ->virt */
+                               __u64           *block_sizes; /* NULL if all the same */
+                       };
+               };
                struct vd_config conf;
        } *conflist, *currentconf;
        struct dl {
-               struct dl       *next;
+               union {
+                       char space[512];
+                       struct {
+                               struct dl       *next;
+                               int major, minor;
+                               char *devname;
+                               int fd;
+                               unsigned long long size; /* sectors */
+                               int pdnum;      /* index in ->phys */
+                               struct spare_assign *spare;
+                       };
+               };
                struct disk_data disk;
-               int major, minor;
-               char *devname;
-               int fd;
-               unsigned long long size; /* sectors */
-               int pdnum;      /* index in ->phys */
-               struct spare_assign *spare;
                struct vcl *vlist[0]; /* max_part in size */
        } *dlist;
 };
@@ -497,8 +503,10 @@ static void *load_section(int fd, struct ddf_super *super, void *buf,
                /* All pre-allocated sections are a single block */
                if (len != 1)
                        return NULL;
-       } else
-               buf = malloc(len<<9);
+       } else {
+               posix_memalign(&buf, 512, len<<9);
+       }
+
        if (!buf)
                return NULL;
 
@@ -633,8 +641,9 @@ static int load_ddf_local(int fd, struct ddf_super *super,
        unsigned long long dsize;
 
        /* First the local disk info */
-       dl = malloc(sizeof(*dl) +
-                   (super->max_part) * sizeof(dl->vlist[0]));
+       posix_memalign((void**)&dl, 512,
+                      sizeof(*dl) +
+                      (super->max_part) * sizeof(dl->vlist[0]));
 
        load_section(fd, super, &dl->disk,
                     super->active->data_section_offset,
@@ -683,7 +692,8 @@ static int load_ddf_local(int fd, struct ddf_super *super,
                if (vd->magic == DDF_SPARE_ASSIGN_MAGIC) {
                        if (dl->spare)
                                continue;
-                       dl->spare = malloc(super->conf_rec_len*512);
+                       posix_memalign((void**)&dl->spare, 512,
+                                      super->conf_rec_len*512);
                        memcpy(dl->spare, vd, super->conf_rec_len*512);
                        continue;
                }
@@ -701,8 +711,9 @@ static int load_ddf_local(int fd, struct ddf_super *super,
                            __be32_to_cpu(vcl->conf.seqnum))
                                continue;
                } else {
-                       vcl = malloc(super->conf_rec_len*512 +
-                                    offsetof(struct vcl, conf));
+                       posix_memalign((void**)&vcl, 512,
+                                      (super->conf_rec_len*512 +
+                                       offsetof(struct vcl, conf)));
                        vcl->next = super->conflist;
                        vcl->block_sizes = NULL; /* FIXME not for CONCAT */
                        super->conflist = vcl;
@@ -766,8 +777,7 @@ static int load_super_ddf(struct supertype *st, int fd,
                }
        }
 
-       super = malloc(sizeof(*super));
-       if (!super) {
+       if (posix_memalign((void**)&super, 512, sizeof(*super))!= 0) {
                fprintf(stderr, Name ": malloc of %zu failed.\n",
                        sizeof(*super));
                return 1;
@@ -1276,6 +1286,8 @@ static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info)
 //     info->disk.raid_disk = find refnum in the table and use index;
 //     info->disk.state = ???;
 
+       info->container_member = ddf->currentconf->vcnum;
+
        info->resync_start = 0;
        if (!(ddf->virt->entries[info->container_member].state
              & DDF_state_inconsistent)  &&
@@ -1443,7 +1455,7 @@ static int init_super_ddf(struct supertype *st,
                return init_super_ddf_bvd(st, info, size, name, homehost,
                                          uuid);
 
-       ddf = malloc(sizeof(*ddf));
+       posix_memalign((void**)&ddf, 512, sizeof(*ddf));
        memset(ddf, 0, sizeof(*ddf));
        ddf->dlist = NULL; /* no physical disks yet */
        ddf->conflist = NULL; /* No virtual disks yet */
@@ -1570,7 +1582,8 @@ static int init_super_ddf(struct supertype *st,
        memset(ddf->controller.pad, 0xff, 8);
        memset(ddf->controller.vendor_data, 0xff, 448);
 
-       pd = ddf->phys = malloc(pdsize);
+       posix_memalign((void**)&pd, 512, pdsize);
+       ddf->phys = pd;
        ddf->pdsize = pdsize;
 
        memset(pd, 0xff, pdsize);
@@ -1580,7 +1593,8 @@ static int init_super_ddf(struct supertype *st,
        pd->max_pdes = __cpu_to_be16(max_phys_disks);
        memset(pd->pad, 0xff, 52);
 
-       vd = ddf->virt = malloc(vdsize);
+       posix_memalign((void**)&vd, 512, vdsize);
+       ddf->virt = vd;
        ddf->vdsize = vdsize;
        memset(vd, 0, vdsize);
        vd->magic = DDF_VIRT_RECORDS_MAGIC;
@@ -1805,7 +1819,8 @@ static int init_super_ddf_bvd(struct supertype *st,
                __cpu_to_be16(__be16_to_cpu(ddf->virt->populated_vdes)+1);
 
        /* Now create a new vd_config */
-       vcl = malloc(offsetof(struct vcl, conf) + ddf->conf_rec_len * 512);
+       posix_memalign((void**)&vcl, 512,
+                      (offsetof(struct vcl, conf) + ddf->conf_rec_len * 512));
        vcl->lba_offset = (__u64*) &vcl->conf.phys_refnum[ddf->mppe];
        vcl->vcnum = venum;
        sprintf(st->subarray, "%d", venum);
@@ -1974,7 +1989,8 @@ static void add_to_super_ddf(struct supertype *st,
         * a phys_disk entry and a more detailed disk_data entry.
         */
        fstat(fd, &stb);
-       dd = malloc(sizeof(*dd) + sizeof(dd->vlist[0]) * ddf->max_part);
+       posix_memalign((void**)&dd, 512,
+                      sizeof(*dd) + sizeof(dd->vlist[0]) * ddf->max_part);
        dd->major = major(stb.st_rdev);
        dd->minor = minor(stb.st_rdev);
        dd->devname = devname;
@@ -2037,7 +2053,7 @@ static void add_to_super_ddf(struct supertype *st,
 
 #ifndef MDASSEMBLE
 
-static unsigned char null_conf[4096];
+static unsigned char null_conf[4096+512];
 
 static int __write_init_super_ddf(struct supertype *st, int do_close)
 {
@@ -2109,14 +2125,15 @@ static int __write_init_super_ddf(struct supertype *st, int do_close)
                                c->conf.crc = calc_crc(&c->conf, conf_size);
                                write(fd, &c->conf, conf_size);
                        } else {
+                               char *null_aligned = (char*)((((unsigned long)null_conf)+511)&~511UL);
                                if (null_conf[0] != 0xff)
                                        memset(null_conf, 0xff, sizeof(null_conf));
                                int togo = conf_size;
-                               while (togo > sizeof(null_conf)) {
-                                       write(fd, null_conf, sizeof(null_conf));
-                                       togo -= sizeof(null_conf);
+                               while (togo > sizeof(null_conf)-512) {
+                                       write(fd, null_aligned, sizeof(null_conf)-512);
+                                       togo -= sizeof(null_conf)-512;
                                }
-                               write(fd, null_conf, togo);
+                               write(fd, null_aligned, togo);
                        }
                }
                d->disk.crc = calc_crc(&d->disk, 512);
@@ -2175,20 +2192,24 @@ static __u64 avail_size_ddf(struct supertype *st, __u64 devsize)
 }
 
 #ifndef MDASSEMBLE
-static int validate_geometry_ddf_container(struct supertype *st,
-                                   int level, int layout, int raiddisks,
-                                   int chunk, unsigned long long size,
-                                   char *dev, unsigned long long *freesize);
+static int
+validate_geometry_ddf_container(struct supertype *st,
+                               int level, int layout, int raiddisks,
+                               int chunk, unsigned long long size,
+                               char *dev, unsigned long long *freesize,
+                               int verbose);
 
 static int validate_geometry_ddf_bvd(struct supertype *st,
                                     int level, int layout, int raiddisks,
                                     int chunk, unsigned long long size,
-                                    char *dev, unsigned long long *freesize);
+                                    char *dev, unsigned long long *freesize,
+                                    int verbose);
 
 static int validate_geometry_ddf(struct supertype *st,
-                         int level, int layout, int raiddisks,
-                         int chunk, unsigned long long size,
-                         char *dev, unsigned long long *freesize)
+                                int level, int layout, int raiddisks,
+                                int chunk, unsigned long long size,
+                                char *dev, unsigned long long *freesize,
+                                int verbose)
 {
        int fd;
        struct mdinfo *sra;
@@ -2204,8 +2225,9 @@ static int validate_geometry_ddf(struct supertype *st,
        if (level == LEVEL_CONTAINER) {
                /* Must be a fresh device to add to a container */
                return validate_geometry_ddf_container(st, level, layout,
-                                              raiddisks,
-                                              chunk, size, dev, freesize);
+                                                      raiddisks, chunk,
+                                                      size, dev, freesize,
+                                                      verbose);
        }
 
        if (st->sb) {
@@ -2214,7 +2236,8 @@ static int validate_geometry_ddf(struct supertype *st,
                 * Should make a distinction one day.
                 */
                return validate_geometry_ddf_bvd(st, level, layout, raiddisks,
-                                                chunk, size, dev, freesize);
+                                                chunk, size, dev, freesize,
+                                                verbose);
        }
        if (!dev) {
                /* Initial sanity check.  Exclude illegal levels. */
@@ -2248,22 +2271,26 @@ static int validate_geometry_ddf(struct supertype *st,
                        /* Somehow return the fact that we have enough */
                }
 
-               fprintf(stderr,
-                       Name ": Cannot create this array on device %s\n",
-                       dev);
+               if (verbose)
+                       fprintf(stderr,
+                               Name ": ddf: Cannot create this array "
+                               "on device %s\n",
+                               dev);
                return 0;
        }
        if (errno != EBUSY || (fd = open(dev, O_RDONLY, 0)) < 0) {
-               fprintf(stderr, Name ": Cannot open %s: %s\n",
-                       dev, strerror(errno));
+               if (verbose)
+                       fprintf(stderr, Name ": ddf: Cannot open %s: %s\n",
+                               dev, strerror(errno));
                return 0;
        }
        /* Well, it is in use by someone, maybe a 'ddf' container. */
        cfd = open_container(fd);
        if (cfd < 0) {
                close(fd);
-               fprintf(stderr, Name ": Cannot use %s: It is busy\n",
-                       dev);
+               if (verbose)
+                       fprintf(stderr, Name ": ddf: Cannot use %s: %s\n",
+                               dev, strerror(EBUSY));
                return 0;
        }
        sra = sysfs_read(cfd, 0, GET_VERSION);
@@ -2280,7 +2307,8 @@ static int validate_geometry_ddf(struct supertype *st,
                        close(cfd);
                        return validate_geometry_ddf_bvd(st, level, layout,
                                                         raiddisks, chunk, size,
-                                                        dev, freesize);
+                                                        dev, freesize,
+                                                        verbose);
                }
                close(cfd);
        } else /* device may belong to a different container */
@@ -2289,10 +2317,12 @@ static int validate_geometry_ddf(struct supertype *st,
        return 1;
 }
 
-static int validate_geometry_ddf_container(struct supertype *st,
-                                  int level, int layout, int raiddisks,
-                                  int chunk, unsigned long long size,
-                                  char *dev, unsigned long long *freesize)
+static int
+validate_geometry_ddf_container(struct supertype *st,
+                               int level, int layout, int raiddisks,
+                               int chunk, unsigned long long size,
+                               char *dev, unsigned long long *freesize,
+                               int verbose)
 {
        int fd;
        unsigned long long ldsize;
@@ -2304,8 +2334,9 @@ static int validate_geometry_ddf_container(struct supertype *st,
 
        fd = open(dev, O_RDONLY|O_EXCL, 0);
        if (fd < 0) {
-               fprintf(stderr, Name ": Cannot open %s: %s\n",
-                       dev, strerror(errno));
+               if (verbose)
+                       fprintf(stderr, Name ": ddf: Cannot open %s: %s\n",
+                               dev, strerror(errno));
                return 0;
        }
        if (!get_dev_size(fd, dev, &ldsize)) {
@@ -2322,7 +2353,8 @@ static int validate_geometry_ddf_container(struct supertype *st,
 static int validate_geometry_ddf_bvd(struct supertype *st,
                                     int level, int layout, int raiddisks,
                                     int chunk, unsigned long long size,
-                                    char *dev, unsigned long long *freesize)
+                                    char *dev, unsigned long long *freesize,
+                                    int verbose)
 {
        struct stat stb;
        struct ddf_super *ddf = st->sb;
@@ -2367,9 +2399,11 @@ static int validate_geometry_ddf_bvd(struct supertype *st,
                        free(e);
                }
                if (dcnt < raiddisks) {
-                       fprintf(stderr, Name ": Not enough devices with space "
-                               "for this array (%d < %d)\n",
-                               dcnt, raiddisks);
+                       if (verbose)
+                               fprintf(stderr,
+                                       Name ": ddf: Not enough devices with "
+                                       "space for this array (%d < %d)\n",
+                                       dcnt, raiddisks);
                        return 0;
                }
                return 1;
@@ -2385,8 +2419,10 @@ static int validate_geometry_ddf_bvd(struct supertype *st,
                        break;
        }
        if (!dl) {
-               fprintf(stderr, Name ": %s is not in the same DDF set\n",
-                       dev);
+               if (verbose)
+                       fprintf(stderr, Name ": ddf: %s is not in the "
+                               "same DDF set\n",
+                               dev);
                return 0;
        }
        e = get_extents(ddf, dl);
@@ -2425,8 +2461,7 @@ static int load_super_ddf_all(struct supertype *st, int fd,
            strcmp(sra->text_version, "ddf") != 0)
                return 1;
 
-       super = malloc(sizeof(*super));
-       if (!super)
+       if (posix_memalign((void**)&super, 512, sizeof(*super)) != 0)
                return 1;
        memset(super, 0, sizeof(*super));
 
@@ -2571,8 +2606,8 @@ static struct mdinfo *container_content_ddf(struct supertype *st)
                        dev->disk.raid_disk = i;
                        dev->disk.state = (1<<MD_DISK_SYNC)|(1<<MD_DISK_ACTIVE);
 
-                       dev->events = __le32_to_cpu(ddf->primary.seq);
-                       dev->data_offset = vc->lba_offset[i];
+                       dev->events = __be32_to_cpu(ddf->primary.seq);
+                       dev->data_offset = __be64_to_cpu(vc->lba_offset[i]);
                        dev->component_size = __be64_to_cpu(vc->conf.blocks);
                        if (d->devname)
                                strcpy(dev->name, d->devname);
@@ -2584,14 +2619,17 @@ static struct mdinfo *container_content_ddf(struct supertype *st)
 static int store_zero_ddf(struct supertype *st, int fd)
 {
        unsigned long long dsize;
-       char buf[512];
-       memset(buf, 0, 512);
+       void *buf;
 
        if (!get_dev_size(fd, NULL, &dsize))
                return 1;
 
+       posix_memalign(&buf, 512, 512);
+       memset(buf, 0, 512);
+
        lseek64(fd, dsize-512, 0);
        write(fd, buf, 512);
+       free(buf);
        return 0;
 }
 
@@ -2628,7 +2666,7 @@ static int compare_super_ddf(struct supertype *st, struct supertype *tst)
  */
 static int ddf_open_new(struct supertype *c, struct active_array *a, char *inst)
 {
-       fprintf(stderr, "ddf: open_new %s\n", inst);
+       dprintf("ddf: open_new %s\n", inst);
        a->info.container_member = atoi(inst);
        return 0;
 }
@@ -2665,8 +2703,8 @@ static void ddf_set_array_state(struct active_array *a, int consistent)
        if (old != ddf->virt->entries[inst].init_state)
                ddf->updates_pending = 1;
 
-       printf("ddf mark %d %s %llu\n", inst, consistent?"clean":"dirty",
-              a->resync_start);
+       dprintf("ddf mark %d %s %llu\n", inst, consistent?"clean":"dirty",
+               a->resync_start);
 }
 
 /*
@@ -2692,7 +2730,7 @@ static void ddf_set_disk(struct active_array *a, int n, int state)
        int i, st, working;
 
        if (vc == NULL) {
-               fprintf(stderr, "ddf: cannot find instance %d!!\n", inst);
+               dprintf("ddf: cannot find instance %d!!\n", inst);
                return;
        }
        if (pd < 0) {
@@ -2717,7 +2755,7 @@ static void ddf_set_disk(struct active_array *a, int n, int state)
                        ddf->updates_pending = 1;
        }
 
-       fprintf(stderr, "ddf: set_disk %d to %x\n", n, state);
+       dprintf("ddf: set_disk %d to %x\n", n, state);
 
        /* Now we need to check the state of the array and update
         * virtual_disk.entries[n].state.
@@ -2787,7 +2825,7 @@ static void ddf_sync_metadata(struct supertype *st)
                return;
        ddf->updates_pending = 0;
        __write_init_super_ddf(st, 0);
-       fprintf(stderr, "ddf: sync_metadata\n");
+       dprintf("ddf: sync_metadata\n");
 }
 
 static void ddf_process_update(struct supertype *st,
@@ -2830,7 +2868,7 @@ static void ddf_process_update(struct supertype *st,
        int mppe;
        int ent;
 
-//     printf("Process update %x\n", *magic);
+       dprintf("Process update %x\n", *magic);
 
        switch (*magic) {
        case DDF_PHYS_RECORDS_MAGIC:
@@ -2870,7 +2908,7 @@ static void ddf_process_update(struct supertype *st,
                break;
 
        case DDF_VD_CONF_MAGIC:
-//             printf("len %d %d\n", update->len, ddf->conf_rec_len);
+               dprintf("len %d %d\n", update->len, ddf->conf_rec_len);
 
                mppe = __be16_to_cpu(ddf->anchor.max_primary_element_entries);
                if (update->len != ddf->conf_rec_len * 512)
@@ -2879,7 +2917,7 @@ static void ddf_process_update(struct supertype *st,
                for (vcl = ddf->conflist; vcl ; vcl = vcl->next)
                        if (memcmp(vcl->conf.guid, vc->guid, DDF_GUID_LEN) == 0)
                                break;
-//             printf("vcl = %p\n", vcl);
+               dprintf("vcl = %p\n", vcl);
                if (vcl) {
                        /* An update, just copy the phys_refnum and lba_offset
                         * fields
@@ -2904,8 +2942,8 @@ static void ddf_process_update(struct supertype *st,
                                for (dn=0; dn < ddf->mppe ; dn++)
                                        if (vcl->conf.phys_refnum[dn] ==
                                            dl->disk.refnum) {
-//                                             printf("dev %d has %p at %d\n",
-//                                                    dl->pdnum, vcl, vn);
+                                               dprintf("dev %d has %p at %d\n",
+                                                       dl->pdnum, vcl, vn);
                                                dl->vlist[vn++] = vcl;
                                                break;
                                        }
@@ -2948,8 +2986,9 @@ static void ddf_prepare_update(struct supertype *st,
        struct ddf_super *ddf = st->sb;
        __u32 *magic = (__u32*)update->buf;
        if (*magic == DDF_VD_CONF_MAGIC)
-               update->space = malloc(offsetof(struct vcl, conf)
-                                      + ddf->conf_rec_len * 512);
+               posix_memalign(&update->space, 512,
+                              offsetof(struct vcl, conf)
+                              + ddf->conf_rec_len * 512);
 }
 
 /*
@@ -2991,8 +3030,8 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a,
                        working ++;
        }
 
-//     printf("ddf_activate: working=%d (%d) level=%d\n", working, a->info.array.raid_disks,
-//            a->info.array.level);
+       dprintf("ddf_activate: working=%d (%d) level=%d\n", working, a->info.array.raid_disks,
+               a->info.array.level);
        if (working == a->info.array.raid_disks)
                return NULL; /* array not degraded */
        switch (a->info.array.level) {
@@ -3019,7 +3058,7 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a,
                for (d = a->info.devs ; d ; d = d->next)
                        if (d->disk.raid_disk == i)
                                break;
-               printf("found %d: %p %x\n", i, d, d?d->curr_state:0);
+               dprintf("found %d: %p %x\n", i, d, d?d->curr_state:0);
                if (d && (d->state_fd >= 0))
                        continue;
 
@@ -3037,7 +3076,7 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a,
                        for (d2 = a->info.devs ; d2 ; d2 = d2->next)
                                if (d2->disk.major == dl->major &&
                                    d2->disk.minor == dl->minor) {
-                                       printf("%x:%x already in array\n", dl->major, dl->minor);
+                                       dprintf("%x:%x already in array\n", dl->major, dl->minor);
                                        break;
                                }
                        if (d2)
@@ -3065,7 +3104,7 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a,
                        }
                        if ( ! (is_dedicated ||
                                (is_global && global_ok))) {
-                               printf("%x:%x not suitable: %d %d\n", dl->major, dl->minor,
+                               dprintf("%x:%x not suitable: %d %d\n", dl->major, dl->minor,
                                       is_dedicated, is_global);
                                continue;
                        }
@@ -3074,7 +3113,7 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a,
                         * We need a->info.component_size sectors */
                        ex = get_extents(ddf, dl);
                        if (!ex) {
-                               printf("cannot get extents\n");
+                               dprintf("cannot get extents\n");
                                continue;
                        }
                        j = 0; pos = 0;
@@ -3090,8 +3129,8 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a,
 
                        free(ex);
                        if (esize < a->info.component_size) {
-                               printf("%x:%x has no room: %llu %llu\n", dl->major, dl->minor,
-                                      esize, a->info.component_size);
+                               dprintf("%x:%x has no room: %llu %llu\n", dl->major, dl->minor,
+                                       esize, a->info.component_size);
                                /* No room */
                                continue;
                        }
@@ -3109,8 +3148,8 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a,
                        di->container_member = dl->pdnum;
                        di->next = rv;
                        rv = di;
-                       printf("%x:%x to be %d at %llu\n", dl->major, dl->minor,
-                              i, pos);
+                       dprintf("%x:%x to be %d at %llu\n", dl->major, dl->minor,
+                               i, pos);
 
                        break;
                }
@@ -3131,7 +3170,7 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a,
         */
        mu = malloc(sizeof(*mu));
        mu->buf = malloc(ddf->conf_rec_len * 512);
-       mu->space = malloc(sizeof(struct vcl));
+       posix_memalign(&mu->space, 512, sizeof(struct vcl));
        mu->len = ddf->conf_rec_len;
        mu->next = *updates;
        vc = find_vdcr(ddf, a->info.container_member);