summaryrefslogtreecommitdiffstats
path: root/usr.bin/mkimg
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2014-08-09 04:47:12 +0000
committermarcel <marcel@FreeBSD.org>2014-08-09 04:47:12 +0000
commite23364d7200439e53ad8369640337915a6250268 (patch)
treed0be153d536def839debae4be54d84dcbe5056e3 /usr.bin/mkimg
parent4378182c79116dca20a70ac668105091def249f2 (diff)
downloadFreeBSD-src-e23364d7200439e53ad8369640337915a6250268.zip
FreeBSD-src-e23364d7200439e53ad8369640337915a6250268.tar.gz
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
Diffstat (limited to 'usr.bin/mkimg')
-rw-r--r--usr.bin/mkimg/vmdk.c28
1 files changed, 23 insertions, 5 deletions
diff --git a/usr.bin/mkimg/vmdk.c b/usr.bin/mkimg/vmdk.c
index 176b97b..a07d0b8 100644
--- a/usr.bin/mkimg/vmdk.c
+++ b/usr.bin/mkimg/vmdk.c
@@ -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);
OpenPOWER on IntegriCloud