aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block/vdi.c23
1 files changed, 16 insertions, 7 deletions
diff --git a/block/vdi.c b/block/vdi.c
index 3ea4103341..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");
@@ -829,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));