diff options
-rw-r--r-- | block/vdi.c | 23 |
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)); |