#define BLOCK_OPT_STATIC "static"
#define SECTOR_SIZE 512
-#define DEFAULT_CLUSTER_SIZE (1 * MiB)
+#define DEFAULT_CLUSTER_SIZE 1048576
+/* Note: can't use 1 * MiB, because it's passed to stringify() */
#if defined(CONFIG_VDI_DEBUG)
#define VDI_DEBUG 1
uint64_t unused2[7];
} QEMU_PACKED VdiHeader;
+QEMU_BUILD_BUG_ON(sizeof(VdiHeader) != 512);
+
typedef struct {
/* The block map entries are little endian (even in memory). */
uint32_t *bmap;
static void vdi_header_to_cpu(VdiHeader *header)
{
- le32_to_cpus(&header->signature);
- le32_to_cpus(&header->version);
- le32_to_cpus(&header->header_size);
- le32_to_cpus(&header->image_type);
- le32_to_cpus(&header->image_flags);
- le32_to_cpus(&header->offset_bmap);
- le32_to_cpus(&header->offset_data);
- le32_to_cpus(&header->cylinders);
- le32_to_cpus(&header->heads);
- le32_to_cpus(&header->sectors);
- le32_to_cpus(&header->sector_size);
- le64_to_cpus(&header->disk_size);
- le32_to_cpus(&header->block_size);
- le32_to_cpus(&header->block_extra);
- le32_to_cpus(&header->blocks_in_image);
- le32_to_cpus(&header->blocks_allocated);
- qemu_uuid_bswap(&header->uuid_image);
- qemu_uuid_bswap(&header->uuid_last_snap);
- qemu_uuid_bswap(&header->uuid_link);
- qemu_uuid_bswap(&header->uuid_parent);
+ header->signature = le32_to_cpu(header->signature);
+ header->version = le32_to_cpu(header->version);
+ header->header_size = le32_to_cpu(header->header_size);
+ header->image_type = le32_to_cpu(header->image_type);
+ header->image_flags = le32_to_cpu(header->image_flags);
+ header->offset_bmap = le32_to_cpu(header->offset_bmap);
+ header->offset_data = le32_to_cpu(header->offset_data);
+ header->cylinders = le32_to_cpu(header->cylinders);
+ header->heads = le32_to_cpu(header->heads);
+ header->sectors = le32_to_cpu(header->sectors);
+ header->sector_size = le32_to_cpu(header->sector_size);
+ header->disk_size = le64_to_cpu(header->disk_size);
+ header->block_size = le32_to_cpu(header->block_size);
+ header->block_extra = le32_to_cpu(header->block_extra);
+ header->blocks_in_image = le32_to_cpu(header->blocks_in_image);
+ header->blocks_allocated = le32_to_cpu(header->blocks_allocated);
+ header->uuid_image = qemu_uuid_bswap(header->uuid_image);
+ header->uuid_last_snap = qemu_uuid_bswap(header->uuid_last_snap);
+ header->uuid_link = qemu_uuid_bswap(header->uuid_link);
+ header->uuid_parent = qemu_uuid_bswap(header->uuid_parent);
}
static void vdi_header_to_le(VdiHeader *header)
{
- cpu_to_le32s(&header->signature);
- cpu_to_le32s(&header->version);
- cpu_to_le32s(&header->header_size);
- cpu_to_le32s(&header->image_type);
- cpu_to_le32s(&header->image_flags);
- cpu_to_le32s(&header->offset_bmap);
- cpu_to_le32s(&header->offset_data);
- cpu_to_le32s(&header->cylinders);
- cpu_to_le32s(&header->heads);
- cpu_to_le32s(&header->sectors);
- cpu_to_le32s(&header->sector_size);
- cpu_to_le64s(&header->disk_size);
- cpu_to_le32s(&header->block_size);
- cpu_to_le32s(&header->block_extra);
- cpu_to_le32s(&header->blocks_in_image);
- cpu_to_le32s(&header->blocks_allocated);
- qemu_uuid_bswap(&header->uuid_image);
- qemu_uuid_bswap(&header->uuid_last_snap);
- qemu_uuid_bswap(&header->uuid_link);
- qemu_uuid_bswap(&header->uuid_parent);
+ header->signature = cpu_to_le32(header->signature);
+ header->version = cpu_to_le32(header->version);
+ header->header_size = cpu_to_le32(header->header_size);
+ header->image_type = cpu_to_le32(header->image_type);
+ header->image_flags = cpu_to_le32(header->image_flags);
+ header->offset_bmap = cpu_to_le32(header->offset_bmap);
+ header->offset_data = cpu_to_le32(header->offset_data);
+ header->cylinders = cpu_to_le32(header->cylinders);
+ header->heads = cpu_to_le32(header->heads);
+ header->sectors = cpu_to_le32(header->sectors);
+ header->sector_size = cpu_to_le32(header->sector_size);
+ header->disk_size = cpu_to_le64(header->disk_size);
+ header->block_size = cpu_to_le32(header->block_size);
+ header->block_extra = cpu_to_le32(header->block_extra);
+ header->blocks_in_image = cpu_to_le32(header->blocks_in_image);
+ header->blocks_allocated = cpu_to_le32(header->blocks_allocated);
+ header->uuid_image = qemu_uuid_bswap(header->uuid_image);
+ header->uuid_last_snap = qemu_uuid_bswap(header->uuid_last_snap);
+ header->uuid_link = qemu_uuid_bswap(header->uuid_link);
+ header->uuid_parent = qemu_uuid_bswap(header->uuid_parent);
}
static void vdi_header_print(VdiHeader *header)
{
- char uuid[37];
+ char uuidstr[37];
+ QemuUUID uuid;
logout("text %s", header->text);
logout("signature 0x%08x\n", header->signature);
logout("header size 0x%04x\n", header->header_size);
logout("block extra 0x%04x\n", header->block_extra);
logout("blocks tot. 0x%04x\n", header->blocks_in_image);
logout("blocks all. 0x%04x\n", header->blocks_allocated);
- qemu_uuid_unparse(&header->uuid_image, uuid);
- logout("uuid image %s\n", uuid);
- qemu_uuid_unparse(&header->uuid_last_snap, uuid);
- logout("uuid snap %s\n", uuid);
- qemu_uuid_unparse(&header->uuid_link, uuid);
- logout("uuid link %s\n", uuid);
- qemu_uuid_unparse(&header->uuid_parent, uuid);
- logout("uuid parent %s\n", uuid);
+ uuid = header->uuid_image;
+ qemu_uuid_unparse(&uuid, uuidstr);
+ logout("uuid image %s\n", uuidstr);
+ uuid = header->uuid_last_snap;
+ qemu_uuid_unparse(&uuid, uuidstr);
+ logout("uuid snap %s\n", uuidstr);
+ uuid = header->uuid_link;
+ qemu_uuid_unparse(&uuid, uuidstr);
+ logout("uuid link %s\n", uuidstr);
+ uuid = header->uuid_parent;
+ qemu_uuid_unparse(&uuid, uuidstr);
+ logout("uuid parent %s\n", uuidstr);
}
static int coroutine_fn vdi_co_check(BlockDriverState *bs, BdrvCheckResult *res,
size_t bmap_size;
int ret;
Error *local_err = NULL;
+ QemuUUID uuid_link, uuid_parent;
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
false, errp);
logout("\n");
- ret = bdrv_read(bs->file, 0, (uint8_t *)&header, 1);
+ ret = bdrv_pread(bs->file, 0, &header, sizeof(header));
if (ret < 0) {
goto fail;
}
goto fail;
}
+ uuid_link = header.uuid_link;
+ uuid_parent = header.uuid_parent;
+
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
goto fail;
} else if (header.block_size != DEFAULT_CLUSTER_SIZE) {
error_setg(errp, "unsupported VDI image (block size %" PRIu32
- " is not %" PRIu64 ")",
+ " is not %" PRIu32 ")",
header.block_size, DEFAULT_CLUSTER_SIZE);
ret = -ENOTSUP;
goto fail;
(uint64_t)header.blocks_in_image * header.block_size);
ret = -ENOTSUP;
goto fail;
- } else if (!qemu_uuid_is_null(&header.uuid_link)) {
+ } else if (!qemu_uuid_is_null(&uuid_link)) {
error_setg(errp, "unsupported VDI image (non-NULL link UUID)");
ret = -ENOTSUP;
goto fail;
- } else if (!qemu_uuid_is_null(&header.uuid_parent)) {
+ } else if (!qemu_uuid_is_null(&uuid_parent)) {
error_setg(errp, "unsupported VDI image (non-NULL parent UUID)");
ret = -ENOTSUP;
goto fail;
goto fail;
}
- ret = bdrv_read(bs->file, s->bmap_sector, (uint8_t *)s->bmap,
- bmap_size);
+ ret = bdrv_pread(bs->file, header.offset_bmap, s->bmap,
+ bmap_size * SECTOR_SIZE);
if (ret < 0) {
goto fail_free_bmap;
}
assert(VDI_IS_ALLOCATED(bmap_first));
*header = s->header;
vdi_header_to_le(header);
- ret = bdrv_write(bs->file, 0, block, 1);
+ ret = bdrv_pwrite(bs->file, 0, block, sizeof(VdiHeader));
g_free(block);
block = NULL;
base = ((uint8_t *)&s->bmap[0]) + bmap_first * SECTOR_SIZE;
logout("will write %u block map sectors starting from entry %u\n",
n_sectors, bmap_first);
- ret = bdrv_write(bs->file, offset, base, n_sectors);
+ ret = bdrv_pwrite(bs->file, offset * SECTOR_SIZE, base,
+ n_sectors * SECTOR_SIZE);
}
- return ret;
+ return ret < 0 ? ret : 0;
}
static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
BlockDriverState *bs_file = NULL;
BlockBackend *blk = NULL;
uint32_t *bmap = NULL;
+ QemuUUID uuid;
assert(create_options->driver == BLOCKDEV_DRIVER_VDI);
vdi_opts = &create_options->u.vdi;
goto exit;
}
- blk = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
+ blk = blk_new(bdrv_get_aio_context(bs_file),
+ BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
ret = blk_insert_bs(blk, bs_file, errp);
if (ret < 0) {
goto exit;
if (image_type == VDI_TYPE_STATIC) {
header.blocks_allocated = blocks;
}
- qemu_uuid_generate(&header.uuid_image);
- qemu_uuid_generate(&header.uuid_last_snap);
+ qemu_uuid_generate(&uuid);
+ header.uuid_image = uuid;
+ qemu_uuid_generate(&uuid);
+ header.uuid_last_snap = uuid;
/* There is no need to set header.uuid_link or header.uuid_parent here. */
if (VDI_DEBUG) {
vdi_header_print(&header);