svn commit: r268646 - head/usr.bin/mkimg

Marcel Moolenaar marcel at FreeBSD.org
Tue Jul 15 04:39:25 UTC 2014


Author: marcel
Date: Tue Jul 15 04:39:23 2014
New Revision: 268646
URL: http://svnweb.freebsd.org/changeset/base/268646

Log:
  Add image_data() for checking whether a sequence of blocks has data.
  Use this for VHD and VMDK to avoid allocating space in the image
  for empty sectors.
  
  Note that this negatively affects performance because mkimg uses a
  temporary file for the intermediate storage. When mkimg has better
  internal book keeping, performance can be significantly improved.

Modified:
  head/usr.bin/mkimg/image.c
  head/usr.bin/mkimg/image.h
  head/usr.bin/mkimg/vhd.c
  head/usr.bin/mkimg/vmdk.c

Modified: head/usr.bin/mkimg/image.c
==============================================================================
--- head/usr.bin/mkimg/image.c	Tue Jul 15 04:33:11 2014	(r268645)
+++ head/usr.bin/mkimg/image.c	Tue Jul 15 04:39:23 2014	(r268646)
@@ -94,12 +94,19 @@ image_copyin(lba_t blk, int fd, uint64_t
 int
 image_copyout(int fd)
 {
-	off_t ofs;
 	int error;
 
 	error = image_copyout_region(fd, 0, image_size);
-	if (error)
-		return (error);
+	if (!error)
+		error = image_copyout_done(fd);
+	return (error);
+}
+
+int
+image_copyout_done(int fd)
+{
+	off_t ofs;
+	int error;
 
 	ofs = lseek(fd, 0L, SEEK_CUR);
 	if (ofs == -1)
@@ -148,6 +155,33 @@ image_copyout_region(int fd, lba_t blk, 
 	return (error);
 }
 
+int
+image_data(lba_t blk, lba_t size)
+{
+	char *buffer, *p;
+
+	blk *= secsz;
+	if (lseek(image_fd, blk, SEEK_SET) != blk)
+		return (1);
+
+	size *= secsz;
+	buffer = malloc(size);
+	if (buffer == NULL)
+		return (1);
+
+	if (read(image_fd, buffer, size) != (ssize_t)size) {
+		free(buffer);
+		return (1);
+	}
+
+	p = buffer;
+	while (size > 0 && *p == '\0')
+		size--, p++;
+
+	free(buffer);
+	return ((size == 0) ? 0 : 1);
+}
+
 lba_t
 image_get_size(void)
 {

Modified: head/usr.bin/mkimg/image.h
==============================================================================
--- head/usr.bin/mkimg/image.h	Tue Jul 15 04:33:11 2014	(r268645)
+++ head/usr.bin/mkimg/image.h	Tue Jul 15 04:39:23 2014	(r268646)
@@ -33,7 +33,9 @@ typedef int64_t lba_t;
 
 int image_copyin(lba_t blk, int fd, uint64_t *sizep);
 int image_copyout(int fd);
+int image_copyout_done(int fd);
 int image_copyout_region(int fd, lba_t blk, lba_t size);
+int image_data(lba_t blk, lba_t size);
 lba_t image_get_size(void);
 int image_init(void);
 int image_set_size(lba_t blk);

Modified: head/usr.bin/mkimg/vhd.c
==============================================================================
--- head/usr.bin/mkimg/vhd.c	Tue Jul 15 04:33:11 2014	(r268645)
+++ head/usr.bin/mkimg/vhd.c	Tue Jul 15 04:39:23 2014	(r268646)
@@ -214,7 +214,7 @@ vhd_write(int fd)
 	struct vhd_dyn_header header;
 	uuid_t id;
 	uint64_t imgsz;
-	lba_t blk, nblks;
+	lba_t blk, blkcnt, nblks;
 	uint32_t *bat;
 	void *bitmap;
 	size_t batsz;
@@ -260,10 +260,14 @@ vhd_write(int fd)
 	if (bat == NULL)
 		return (errno);
 	memset(bat, 0xff, batsz);
+	blkcnt = VHD_BLOCK_SIZE / secsz;
 	sector = (sizeof(footer) + sizeof(header) + batsz) / VHD_SECTOR_SIZE;
 	for (entry = 0; entry < bat_entries; entry++) {
-		be32enc(&bat[entry], sector);
-		sector += (VHD_BLOCK_SIZE / VHD_SECTOR_SIZE) + 1;
+		blk = entry * blkcnt;
+		if (image_data(blk, blkcnt)) {
+			be32enc(&bat[entry], sector);
+			sector += (VHD_BLOCK_SIZE / VHD_SECTOR_SIZE) + 1;
+		}
 	}
 	if (sparse_write(fd, bat, batsz) < 0) {
 		free(bat);
@@ -277,16 +281,21 @@ vhd_write(int fd)
 	memset(bitmap, 0xff, VHD_SECTOR_SIZE);
 
 	blk = 0;
+	blkcnt = VHD_BLOCK_SIZE / secsz;
 	nblks = image_get_size();
 	while (blk < nblks) {
+		if (!image_data(blk, blkcnt)) {
+			blk += blkcnt;
+			continue;
+		}
 		if (sparse_write(fd, bitmap, VHD_SECTOR_SIZE) < 0) {
 			error = errno;
 			break;
 		}
-		error = image_copyout_region(fd, blk, VHD_BLOCK_SIZE / secsz);
+		error = image_copyout_region(fd, blk, blkcnt);
 		if (error)
 			break;
-		blk += VHD_BLOCK_SIZE / secsz;
+		blk += blkcnt;
 	}
 	free(bitmap);
 	if (blk != nblks)

Modified: head/usr.bin/mkimg/vmdk.c
==============================================================================
--- head/usr.bin/mkimg/vmdk.c	Tue Jul 15 04:33:11 2014	(r268645)
+++ head/usr.bin/mkimg/vmdk.c	Tue Jul 15 04:39:23 2014	(r268646)
@@ -114,8 +114,9 @@ vmdk_write(int fd)
 	char *buf, *desc;
 	off_t cur, lim;
 	uint64_t imagesz;
+	lba_t blkofs, blkcnt;
 	size_t gdsz, gtsz;
-	uint32_t sec;
+	uint32_t sec, cursec;
 	int error, desc_len, n, ngrains, ngts;
 
 	imagesz = (image_get_size() * secsz) / VMDK_SECTOR_SIZE;
@@ -178,8 +179,15 @@ vmdk_write(int fd)
 		return (ENOMEM);
 	}
 
-	for (n = 0; n < ngrains; n++)
-		le32enc(gt + n, sec + n * grainsz);
+	cursec = sec;
+	blkcnt = (grainsz * VMDK_SECTOR_SIZE) / secsz;
+	for (n = 0; n < ngrains; n++) {
+		blkofs = n * blkcnt;
+		if (image_data(blkofs, blkcnt)) {
+			le32enc(gt + n, cursec);
+			cursec += grainsz;
+		}
+	}
 
 	error = 0;
 	if (!error && sparse_write(fd, &hdr, VMDK_SECTOR_SIZE) < 0)
@@ -210,9 +218,19 @@ vmdk_write(int fd)
 		if (buf != NULL)
 			free(buf);
 	}
-	if (!error)
-		error = image_copyout(fd);
-	return (error);
+	if (error)
+		return (error);
+
+	blkcnt = (grainsz * VMDK_SECTOR_SIZE) / secsz;
+	for (n = 0; n < ngrains; n++) {
+		blkofs = n * blkcnt;
+		if (image_data(blkofs, blkcnt)) {
+			error = image_copyout_region(fd, blkofs, blkcnt);
+			if (error)
+				return (error);
+		}
+	}
+	return (image_copyout_done(fd));
 }
 
 static struct mkimg_format vmdk_format = {


More information about the svn-src-all mailing list