summaryrefslogtreecommitdiffstats
path: root/usr.bin/mkimg
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2014-07-15 04:39:23 +0000
committermarcel <marcel@FreeBSD.org>2014-07-15 04:39:23 +0000
commitca1d5922c55b13221ec863517dce4d9329318a56 (patch)
tree2602f3f98edd6c6d4a9873d48cbac8b567d2f01a /usr.bin/mkimg
parentb2edcea2f09e8ae340319af5a1ef2fd254173fe7 (diff)
downloadFreeBSD-src-ca1d5922c55b13221ec863517dce4d9329318a56.zip
FreeBSD-src-ca1d5922c55b13221ec863517dce4d9329318a56.tar.gz
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.
Diffstat (limited to 'usr.bin/mkimg')
-rw-r--r--usr.bin/mkimg/image.c40
-rw-r--r--usr.bin/mkimg/image.h2
-rw-r--r--usr.bin/mkimg/vhd.c19
-rw-r--r--usr.bin/mkimg/vmdk.c30
4 files changed, 77 insertions, 14 deletions
diff --git a/usr.bin/mkimg/image.c b/usr.bin/mkimg/image.c
index 264c5b2..f448d98 100644
--- a/usr.bin/mkimg/image.c
+++ b/usr.bin/mkimg/image.c
@@ -94,12 +94,19 @@ image_copyin(lba_t blk, int fd, uint64_t *sizep)
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, lba_t size)
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)
{
diff --git a/usr.bin/mkimg/image.h b/usr.bin/mkimg/image.h
index c4e842e..ce195d9 100644
--- a/usr.bin/mkimg/image.h
+++ b/usr.bin/mkimg/image.h
@@ -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);
diff --git a/usr.bin/mkimg/vhd.c b/usr.bin/mkimg/vhd.c
index b0ce0cc..d747450 100644
--- a/usr.bin/mkimg/vhd.c
+++ b/usr.bin/mkimg/vhd.c
@@ -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)
diff --git a/usr.bin/mkimg/vmdk.c b/usr.bin/mkimg/vmdk.c
index af5f786..176b97b 100644
--- a/usr.bin/mkimg/vmdk.c
+++ b/usr.bin/mkimg/vmdk.c
@@ -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 = {
OpenPOWER on IntegriCloud