diff options
author | Anthony Liguori <aliguori@us.ibm.com> | 2010-05-17 13:17:34 -0500 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2010-05-17 13:17:34 -0500 |
commit | 129414184e79e887a4028f153f3b50b92354a6fc (patch) | |
tree | ed0c48e3df6d86f6cf750170daa4270d9305e5e8 /block/vdi.c | |
parent | f7ce72878c05dacc5f52374b69e61d00556a185b (diff) | |
parent | 35ed5de6be186d46ff3e33554f32151fba0f401f (diff) |
Merge remote branch 'kwolf/for-anthony' into staging
Diffstat (limited to 'block/vdi.c')
-rw-r--r-- | block/vdi.c | 34 |
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; |