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) {
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);
}
}
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;
}
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) {
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;
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;
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,
__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");
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++;
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++)