*/
#include "qemu-common.h"
-#include "block_int.h"
-#include "module.h"
-#include "migration.h"
+#include "block/block_int.h"
+#include "qemu/module.h"
+#include "migration/migration.h"
#if defined(CONFIG_UUID)
#include <uuid/uuid.h>
#else
/* TODO: move uuid emulation to some central place in QEMU. */
-#include "sysemu.h" /* UUID_FMT */
+#include "sysemu/sysemu.h" /* UUID_FMT */
typedef unsigned char uuid_t[16];
-void uuid_generate(uuid_t out);
-int uuid_is_null(const uuid_t uu);
-void uuid_unparse(const uuid_t uu, char *out);
#endif
/* Code configuration options. */
#define VDI_IS_ALLOCATED(X) ((X) < VDI_DISCARDED)
#if !defined(CONFIG_UUID)
-void uuid_generate(uuid_t out)
+static inline void uuid_generate(uuid_t out)
{
memset(out, 0, sizeof(uuid_t));
}
-int uuid_is_null(const uuid_t uu)
+static inline int uuid_is_null(const uuid_t uu)
{
uuid_t null_uuid = { 0 };
return memcmp(uu, null_uuid, sizeof(uuid_t)) == 0;
}
-void uuid_unparse(const uuid_t uu, char *out)
+static inline void uuid_unparse(const uuid_t uu, char *out)
{
snprintf(out, 37, UUID_FMT,
uu[0], uu[1], uu[2], uu[3], uu[4], uu[5], uu[6], uu[7],
{
char uuid[37];
logout("text %s", header->text);
- logout("signature 0x%04x\n", header->signature);
+ logout("signature 0x%08x\n", header->signature);
logout("header size 0x%04x\n", header->header_size);
logout("image type 0x%04x\n", header->image_type);
logout("image flags 0x%04x\n", header->image_flags);
return result;
}
-static int vdi_open(BlockDriverState *bs, int flags)
+static int vdi_open(BlockDriverState *bs, QDict *options, int flags)
{
BDRVVdiState *s = bs->opaque;
VdiHeader header;
size_t bmap_size;
+ int ret;
logout("\n");
- if (bdrv_read(bs->file, 0, (uint8_t *)&header, 1) < 0) {
+ ret = bdrv_read(bs->file, 0, (uint8_t *)&header, 1);
+ if (ret < 0) {
goto fail;
}
header.disk_size &= ~(SECTOR_SIZE - 1);
}
- if (header.version != VDI_VERSION_1_1) {
+ if (header.signature != VDI_SIGNATURE) {
+ logout("bad vdi signature %08x\n", header.signature);
+ ret = -EMEDIUMTYPE;
+ goto fail;
+ } else if (header.version != VDI_VERSION_1_1) {
logout("unsupported version %u.%u\n",
header.version >> 16, header.version & 0xffff);
+ ret = -ENOTSUP;
goto fail;
} else if (header.offset_bmap % SECTOR_SIZE != 0) {
/* We only support block maps which start on a sector boundary. */
logout("unsupported block map offset 0x%x B\n", header.offset_bmap);
+ ret = -ENOTSUP;
goto fail;
} else if (header.offset_data % SECTOR_SIZE != 0) {
/* We only support data blocks which start on a sector boundary. */
logout("unsupported data offset 0x%x B\n", header.offset_data);
+ ret = -ENOTSUP;
goto fail;
} else if (header.sector_size != SECTOR_SIZE) {
logout("unsupported sector size %u B\n", header.sector_size);
+ ret = -ENOTSUP;
goto fail;
} else if (header.block_size != 1 * MiB) {
logout("unsupported block size %u B\n", header.block_size);
+ ret = -ENOTSUP;
goto fail;
} else if (header.disk_size >
(uint64_t)header.blocks_in_image * header.block_size) {
logout("unsupported disk size %" PRIu64 " B\n", header.disk_size);
+ ret = -ENOTSUP;
goto fail;
} else if (!uuid_is_null(header.uuid_link)) {
logout("link uuid != 0, unsupported\n");
+ ret = -ENOTSUP;
goto fail;
} else if (!uuid_is_null(header.uuid_parent)) {
logout("parent uuid != 0, unsupported\n");
+ ret = -ENOTSUP;
goto fail;
}
bmap_size = header.blocks_in_image * sizeof(uint32_t);
bmap_size = (bmap_size + SECTOR_SIZE - 1) / SECTOR_SIZE;
- if (bmap_size > 0) {
- s->bmap = g_malloc(bmap_size * SECTOR_SIZE);
- }
- if (bdrv_read(bs->file, s->bmap_sector, (uint8_t *)s->bmap, bmap_size) < 0) {
+ s->bmap = g_malloc(bmap_size * SECTOR_SIZE);
+ ret = bdrv_read(bs->file, s->bmap_sector, (uint8_t *)s->bmap, bmap_size);
+ if (ret < 0) {
goto fail_free_bmap;
}
g_free(s->bmap);
fail:
- return -1;
+ return ret;
}
-static int coroutine_fn vdi_co_is_allocated(BlockDriverState *bs,
+static int vdi_reopen_prepare(BDRVReopenState *state,
+ BlockReopenQueue *queue, Error **errp)
+{
+ return 0;
+}
+
+static int64_t coroutine_fn vdi_co_get_block_status(BlockDriverState *bs,
int64_t sector_num, int nb_sectors, int *pnum)
{
/* TODO: Check for too large sector_num (in bdrv_is_allocated or here). */
size_t sector_in_block = sector_num % s->block_sectors;
int n_sectors = s->block_sectors - sector_in_block;
uint32_t bmap_entry = le32_to_cpu(s->bmap[bmap_index]);
+ uint64_t offset;
+ int result;
+
logout("%p, %" PRId64 ", %d, %p\n", bs, sector_num, nb_sectors, pnum);
if (n_sectors > nb_sectors) {
n_sectors = nb_sectors;
}
*pnum = n_sectors;
- return VDI_IS_ALLOCATED(bmap_entry);
+ result = VDI_IS_ALLOCATED(bmap_entry);
+ if (!result) {
+ return 0;
+ }
+
+ offset = s->header.offset_data +
+ (uint64_t)bmap_entry * s->block_size +
+ sector_in_block * SECTOR_SIZE;
+ return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | offset;
}
static int vdi_co_read(BlockDriverState *bs,
VdiHeader header;
size_t i;
size_t bmap_size;
- uint32_t *bmap;
logout("\n");
result = -errno;
}
- bmap = NULL;
if (bmap_size > 0) {
- bmap = (uint32_t *)g_malloc0(bmap_size);
- }
- for (i = 0; i < blocks; i++) {
- if (image_type == VDI_TYPE_STATIC) {
- bmap[i] = i;
- } else {
- bmap[i] = VDI_UNALLOCATED;
+ uint32_t *bmap = g_malloc0(bmap_size);
+ for (i = 0; i < blocks; i++) {
+ if (image_type == VDI_TYPE_STATIC) {
+ bmap[i] = i;
+ } else {
+ bmap[i] = VDI_UNALLOCATED;
+ }
}
+ if (write(fd, bmap, bmap_size) < 0) {
+ result = -errno;
+ }
+ g_free(bmap);
}
- if (write(fd, bmap, bmap_size) < 0) {
- result = -errno;
- }
- g_free(bmap);
+
if (image_type == VDI_TYPE_STATIC) {
if (ftruncate(fd, sizeof(header) + bmap_size + blocks * block_size)) {
result = -errno;
.bdrv_probe = vdi_probe,
.bdrv_open = vdi_open,
.bdrv_close = vdi_close,
+ .bdrv_reopen_prepare = vdi_reopen_prepare,
.bdrv_create = vdi_create,
- .bdrv_co_is_allocated = vdi_co_is_allocated,
+ .bdrv_has_zero_init = bdrv_has_zero_init_1,
+ .bdrv_co_get_block_status = vdi_co_get_block_status,
.bdrv_make_empty = vdi_make_empty,
.bdrv_read = vdi_co_read,