aboutsummaryrefslogtreecommitdiff
path: root/block/vdi.c
diff options
context:
space:
mode:
authorAnthony Liguori <aliguori@us.ibm.com>2010-05-17 13:17:34 -0500
committerAnthony Liguori <aliguori@us.ibm.com>2010-05-17 13:17:34 -0500
commit129414184e79e887a4028f153f3b50b92354a6fc (patch)
treeed0c48e3df6d86f6cf750170daa4270d9305e5e8 /block/vdi.c
parentf7ce72878c05dacc5f52374b69e61d00556a185b (diff)
parent35ed5de6be186d46ff3e33554f32151fba0f401f (diff)
Merge remote branch 'kwolf/for-anthony' into staging
Diffstat (limited to 'block/vdi.c')
-rw-r--r--block/vdi.c34
1 files changed, 24 insertions, 10 deletions
diff --git a/block/vdi.c b/block/vdi.c
index 1d257b4838..ee8cc7b1aa 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -393,6 +393,15 @@ static int vdi_open(BlockDriverState *bs, int flags)
vdi_header_print(&header);
#endif
+ if (header.disk_size % SECTOR_SIZE != 0) {
+ /* 'VBoxManage convertfromraw' can create images with odd disk sizes.
+ We accept them but round the disk size to the next multiple of
+ SECTOR_SIZE. */
+ logout("odd disk size %" PRIu64 " B, round up\n", header.disk_size);
+ header.disk_size += SECTOR_SIZE - 1;
+ header.disk_size &= ~(SECTOR_SIZE - 1);
+ }
+
if (header.version != VDI_VERSION_1_1) {
logout("unsupported version %u.%u\n",
header.version >> 16, header.version & 0xffff);
@@ -405,18 +414,15 @@ static int vdi_open(BlockDriverState *bs, int flags)
/* We only support data blocks which start on a sector boundary. */
logout("unsupported data offset 0x%x B\n", header.offset_data);
goto fail;
- } else if (header.disk_size % SECTOR_SIZE != 0) {
- logout("unsupported disk size %" PRIu64 " B\n", header.disk_size);
- goto fail;
} else if (header.sector_size != SECTOR_SIZE) {
logout("unsupported sector size %u B\n", header.sector_size);
goto fail;
} else if (header.block_size != 1 * MiB) {
logout("unsupported block size %u B\n", header.block_size);
goto fail;
- } else if ((header.disk_size + header.block_size - 1) / header.block_size !=
- (uint64_t)header.blocks_in_image) {
- logout("unexpected block number %u B\n", header.blocks_in_image);
+ } else if (header.disk_size >
+ (uint64_t)header.blocks_in_image * header.block_size) {
+ logout("unsupported disk size %" PRIu64 " B\n", header.disk_size);
goto fail;
} else if (!uuid_is_null(header.uuid_link)) {
logout("link uuid != 0, unsupported\n");
@@ -435,7 +441,9 @@ static int vdi_open(BlockDriverState *bs, int flags)
bmap_size = header.blocks_in_image * sizeof(uint32_t);
bmap_size = (bmap_size + SECTOR_SIZE - 1) / SECTOR_SIZE;
- s->bmap = qemu_malloc(bmap_size * SECTOR_SIZE);
+ if (bmap_size > 0) {
+ s->bmap = qemu_malloc(bmap_size * SECTOR_SIZE);
+ }
if (bdrv_read(bs->file, s->bmap_sector, (uint8_t *)s->bmap, bmap_size) < 0) {
goto fail_free_bmap;
}
@@ -469,7 +477,7 @@ static int vdi_is_allocated(BlockDriverState *bs, int64_t sector_num,
static void vdi_aio_cancel(BlockDriverAIOCB *blockacb)
{
/* TODO: This code is untested. How can I get it executed? */
- VdiAIOCB *acb = (VdiAIOCB *)blockacb;
+ VdiAIOCB *acb = container_of(blockacb, VdiAIOCB, common);
logout("\n");
if (acb->hd_aiocb) {
bdrv_aio_cancel(acb->hd_aiocb);
@@ -827,7 +835,10 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options)
return -errno;
}
- blocks = bytes / block_size;
+ /* We need enough blocks to store the given disk size,
+ so always round up. */
+ blocks = (bytes + block_size - 1) / block_size;
+
bmap_size = blocks * sizeof(uint32_t);
bmap_size = ((bmap_size + SECTOR_SIZE - 1) & ~(SECTOR_SIZE -1));
@@ -857,7 +868,10 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options)
result = -errno;
}
- bmap = (uint32_t *)qemu_mallocz(bmap_size);
+ bmap = NULL;
+ if (bmap_size > 0) {
+ bmap = (uint32_t *)qemu_mallocz(bmap_size);
+ }
for (i = 0; i < blocks; i++) {
if (image_type == VDI_TYPE_STATIC) {
bmap[i] = i;