]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
DDF: Simplify allocation of "other BVDs"
authormwilck@arcor.de <mwilck@arcor.de>
Wed, 3 Jul 2013 20:27:53 +0000 (22:27 +0200)
committerNeilBrown <neilb@suse.de>
Mon, 8 Jul 2013 06:48:30 +0000 (16:48 +1000)
Instead of allocating the other_bvds array and every element
separately, allocate all in a single chunk. Also, move allocation
in a subroutine as it's used in several places.

Signed-off-by: Martin Wilck <mwilck@arcor.de>
Signed-off-by: NeilBrown <neilb@suse.de>
super-ddf.c

index c548ceb09845c030812fc08c79ddb0c72ca983ed..7e056f5570ef79ced02c1d19fa15c8ee7e950bad 100644 (file)
@@ -866,13 +866,35 @@ static int load_ddf_global(int fd, struct ddf_super *super, char *devname)
        return 0;
 }
 
+#define DDF_UNUSED_BVD 0xff
+static int alloc_other_bvds(const struct ddf_super *ddf, struct vcl *vcl)
+{
+       unsigned int n_vds = vcl->conf.sec_elmnt_count - 1;
+       unsigned int i, vdsize;
+       void *p;
+       if (n_vds == 0) {
+               vcl->other_bvds = NULL;
+               return 0;
+       }
+       vdsize = ddf->conf_rec_len * 512;
+       if (posix_memalign(&p, 512, n_vds *
+                          (vdsize +  sizeof(struct vd_config *))) != 0)
+               return -1;
+       vcl->other_bvds = (struct vd_config **) (p + n_vds * vdsize);
+       for (i = 0; i < n_vds; i++) {
+               vcl->other_bvds[i] = p + i * vdsize;
+               memset(vcl->other_bvds[i], 0, vdsize);
+               vcl->other_bvds[i]->sec_elmnt_seq = DDF_UNUSED_BVD;
+       }
+       return 0;
+}
+
 static void add_other_bvd(struct vcl *vcl, struct vd_config *vd,
                          unsigned int len)
 {
        int i;
        for (i = 0; i < vcl->conf.sec_elmnt_count-1; i++)
-               if (vcl->other_bvds[i] != NULL &&
-                   vcl->other_bvds[i]->sec_elmnt_seq == vd->sec_elmnt_seq)
+               if (vcl->other_bvds[i]->sec_elmnt_seq == vd->sec_elmnt_seq)
                        break;
 
        if (i < vcl->conf.sec_elmnt_count-1) {
@@ -880,18 +902,13 @@ static void add_other_bvd(struct vcl *vcl, struct vd_config *vd,
                        return;
        } else {
                for (i = 0; i < vcl->conf.sec_elmnt_count-1; i++)
-                       if (vcl->other_bvds[i] == NULL)
+                       if (vcl->other_bvds[i]->sec_elmnt_seq == DDF_UNUSED_BVD)
                                break;
                if (i == vcl->conf.sec_elmnt_count-1) {
                        pr_err("no space for sec level config %u, count is %u\n",
                               vd->sec_elmnt_seq, vcl->conf.sec_elmnt_count);
                        return;
                }
-               if (posix_memalign((void **)&vcl->other_bvds[i], 512, len)
-                   != 0) {
-                       pr_err("%s could not allocate vd buf\n", __func__);
-                       return;
-               }
        }
        memcpy(vcl->other_bvds[i], vd, len);
 }
@@ -1009,12 +1026,13 @@ static int load_ddf_local(int fd, struct ddf_super *super,
                        }
                        vcl->next = super->conflist;
                        vcl->block_sizes = NULL; /* FIXME not for CONCAT */
-                       if (vd->sec_elmnt_count > 1)
-                               vcl->other_bvds =
-                                       xcalloc(vd->sec_elmnt_count - 1,
-                                               sizeof(struct vd_config *));
-                       else
-                               vcl->other_bvds = NULL;
+                       vcl->conf.sec_elmnt_count = vd->sec_elmnt_count;
+                       if (alloc_other_bvds(super, vcl) != 0) {
+                               pr_err("%s could not allocate other bvds\n",
+                                      __func__);
+                               free(vcl);
+                               return 1;
+                       };
                        super->conflist = vcl;
                        dl->vlist[vnum++] = vcl;
                }
@@ -1132,13 +1150,12 @@ static void free_super_ddf(struct supertype *st)
                ddf->conflist = v->next;
                if (v->block_sizes)
                        free(v->block_sizes);
-               if (v->other_bvds) {
-                       int i;
-                       for (i = 0; i < v->conf.sec_elmnt_count-1; i++)
-                               if (v->other_bvds[i] != NULL)
-                                       free(v->other_bvds[i]);
-                       free(v->other_bvds);
-               }
+               if (v->other_bvds)
+                       /*
+                          v->other_bvds[0] points to beginning of buffer,
+                          see alloc_other_bvds()
+                       */
+                       free(v->other_bvds[0]);
                free(v);
        }
        while (ddf->dlist) {
@@ -1666,8 +1683,6 @@ static struct vd_config *find_vdcr(struct ddf_super *ddf, unsigned int inst,
                nsec = n / __be16_to_cpu(conf->prim_elmnt_count);
                if (conf->sec_elmnt_seq != nsec) {
                        for (ibvd = 1; ibvd < conf->sec_elmnt_count; ibvd++) {
-                               if (v->other_bvds[ibvd-1] == NULL)
-                                       continue;
                                if (v->other_bvds[ibvd-1]->sec_elmnt_seq
                                    == nsec)
                                        break;
@@ -2362,8 +2377,6 @@ static int init_super_ddf_bvd(struct supertype *st,
        vcl->lba_offset = (__u64*) &vcl->conf.phys_refnum[ddf->mppe];
        vcl->vcnum = venum;
        vcl->block_sizes = NULL; /* FIXME not for CONCAT */
-       vcl->other_bvds = NULL;
-
        vc = &vcl->conf;
 
        vc->magic = DDF_VD_CONF_MAGIC;
@@ -2380,6 +2393,12 @@ static int init_super_ddf_bvd(struct supertype *st,
                return 0;
        }
        vc->sec_elmnt_seq = 0;
+       if (alloc_other_bvds(ddf, vcl) != 0) {
+               pr_err("%s could not allocate other bvds\n",
+                      __func__);
+               free(vcl);
+               return 0;
+       }
        vc->blocks = __cpu_to_be64(info->size * 2);
        vc->array_blocks = __cpu_to_be64(
                calc_array_size(info->level, info->raid_disks, info->layout,
@@ -3394,7 +3413,7 @@ static int check_secondary(const struct vcl *vc)
        __set_sec_seen(conf->sec_elmnt_seq);
        for (i = 0; i < conf->sec_elmnt_count-1; i++) {
                const struct vd_config *bvd = vc->other_bvds[i];
-               if (bvd == NULL)
+               if (bvd->sec_elmnt_seq == DDF_UNUSED_BVD)
                        continue;
                if (bvd->srl != conf->srl) {
                        pr_err("Inconsistent secondary RAID level across BVDs\n");
@@ -3452,9 +3471,9 @@ static unsigned int get_pd_index_from_refnum(const struct vcl *vc,
 
        for (n = 1; n < vc->conf.sec_elmnt_count; n++) {
                struct vd_config *vd = vc->other_bvds[n-1];
-               if (vd == NULL)
-                       continue;
                sec = vd->sec_elmnt_seq;
+               if (sec == DDF_UNUSED_BVD)
+                       continue;
                for (i = 0, j = 0 ; i < nmax ; i++) {
                        if (vd->phys_refnum[i] != 0xffffffff)
                                j++;
@@ -3756,12 +3775,13 @@ static int compare_super_ddf(struct supertype *st, struct supertype *tst)
 
                vl1->next = first->conflist;
                vl1->block_sizes = NULL;
-               if (vl2->conf.sec_elmnt_count > 1) {
-                       vl1->other_bvds = xcalloc(vl2->conf.sec_elmnt_count - 1,
-                                                 sizeof(struct vd_config *));
-               } else
-                       vl1->other_bvds = NULL;
                memcpy(&vl1->conf, &vl2->conf, first->conf_rec_len*512);
+               if (alloc_other_bvds(first, vl1) != 0) {
+                       pr_err("%s could not allocate other bvds\n",
+                              __func__);
+                       free(vl1);
+                       return 3;
+               }
                vl1->lba_offset = (__u64 *)
                        &vl1->conf.phys_refnum[first->mppe];
                for (vd = 0; vd < max_vds; vd++)