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.
This commit is contained in:
parent
b2edcea2f0
commit
ca1d5922c5
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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 = {
|
||||
|
Loading…
x
Reference in New Issue
Block a user