Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 9 Aug 2014 04:47:12 +0000 (UTC)
From:      Marcel Moolenaar <marcel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r269745 - head/usr.bin/mkimg
Message-ID:  <53e5a7d0.2ec7.26d23fe2@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: marcel
Date: Sat Aug  9 04:47:12 2014
New Revision: 269745
URL: http://svnweb.freebsd.org/changeset/base/269745

Log:
  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

Modified:
  head/usr.bin/mkimg/vmdk.c

Modified: head/usr.bin/mkimg/vmdk.c
==============================================================================
--- head/usr.bin/mkimg/vmdk.c	Fri Aug  8 23:55:22 2014	(r269744)
+++ head/usr.bin/mkimg/vmdk.c	Sat Aug  9 04:47:12 2014	(r269745)
@@ -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);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?53e5a7d0.2ec7.26d23fe2>