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 = {
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to