Create a redundant grain directory and table. Previously we were

cheating by assigning the same sector offset to both directories,
but it seems that VirtualBox doesn't like that. Neither does
qemu from the looks of it.  We now actually write the directory
and table twice.

MFC after:	3 days
This commit is contained in:
Marcel Moolenaar 2014-08-09 04:47:12 +00:00
parent 37fbf89826
commit 6219349311
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=269745

View File

@ -110,7 +110,7 @@ static int
vmdk_write(int fd)
{
struct vmdk_header hdr;
uint32_t *gt, *gd;
uint32_t *gt, *gd, *rgd;
char *buf, *desc;
off_t cur, lim;
uint64_t imagesz;
@ -143,25 +143,37 @@ vmdk_write(int fd)
le32enc(&hdr.ngtes, VMDK_NGTES);
sec = desc_len / VMDK_SECTOR_SIZE + 1;
le64enc(&hdr.rgd_offset, sec);
le64enc(&hdr.gd_offset, sec);
ngrains = imagesz / grainsz;
ngts = (ngrains + VMDK_NGTES - 1) / VMDK_NGTES;
gdsz = (ngts * sizeof(uint32_t) + VMDK_SECTOR_SIZE - 1) &
~(VMDK_SECTOR_SIZE - 1);
gd = calloc(gdsz, 1);
if (gd == NULL) {
free(desc);
return (ENOMEM);
}
le64enc(&hdr.gd_offset, sec);
sec += gdsz / VMDK_SECTOR_SIZE;
for (n = 0; n < ngts; n++) {
le32enc(gd + n, sec);
sec += VMDK_NGTES * sizeof(uint32_t) / VMDK_SECTOR_SIZE;
}
rgd = calloc(gdsz, 1);
if (rgd == NULL) {
free(gd);
free(desc);
return (ENOMEM);
}
le64enc(&hdr.rgd_offset, sec);
sec += gdsz / VMDK_SECTOR_SIZE;
for (n = 0; n < ngts; n++) {
le32enc(rgd + n, sec);
sec += VMDK_NGTES * sizeof(uint32_t) / VMDK_SECTOR_SIZE;
}
sec = (sec + grainsz - 1) & ~(grainsz - 1);
if (verbose)
@ -174,6 +186,7 @@ vmdk_write(int fd)
gtsz = ngts * VMDK_NGTES * sizeof(uint32_t);
gt = calloc(gtsz, 1);
if (gt == NULL) {
free(rgd);
free(gd);
free(desc);
return (ENOMEM);
@ -198,13 +211,18 @@ vmdk_write(int fd)
error = errno;
if (!error && sparse_write(fd, gt, gtsz) < 0)
error = errno;
if (!error && sparse_write(fd, rgd, gdsz) < 0)
error = errno;
if (!error && sparse_write(fd, gt, gtsz) < 0)
error = errno;
free(gt);
free(rgd);
free(gd);
free(desc);
if (error)
return (error);
cur = VMDK_SECTOR_SIZE + desc_len + gdsz + gtsz;
cur = VMDK_SECTOR_SIZE + desc_len + (gdsz + gtsz) * 2;
lim = sec * VMDK_SECTOR_SIZE;
if (cur < lim) {
buf = calloc(VMDK_SECTOR_SIZE, 1);