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;
logout("\n");
bdi->cluster_size = s->block_size;
bdi->vm_state_offset = 0;
- bdi->unallocated_blocks_are_zero = true;
return 0;
}
VdiHeader header;
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);
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
+ BDRV_CHILD_IMAGE, false, errp);
if (!bs->file) {
return -EINVAL;
}
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;
}
- 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;
}
error_setg(&s->migration_blocker, "The vdi format used by node '%s' "
"does not support live migration",
bdrv_get_device_or_node_name(bs));
- ret = migrate_add_blocker(s->migration_blocker, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
+ ret = migrate_add_blocker(s->migration_blocker, errp);
+ if (ret < 0) {
error_free(s->migration_blocker);
goto fail_free_bmap;
}
*pnum = MIN(s->block_size - index_in_block, bytes);
result = VDI_IS_ALLOCATED(bmap_entry);
if (!result) {
- return 0;
+ return BDRV_BLOCK_ZERO;
}
*map = s->header.offset_data + (uint64_t)bmap_entry * s->block_size +
index_in_block;
*file = bs->file->bs;
- return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
+ return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID |
+ (s->header.image_type == VDI_TYPE_STATIC ? BDRV_BLOCK_RECURSE : 0);
}
static int coroutine_fn
logout("finished data write\n");
if (ret < 0) {
+ g_free(block);
return ret;
}
if (block) {
/* One or more new blocks were allocated. */
- VdiHeader *header = (VdiHeader *) block;
+ VdiHeader *header;
uint8_t *base;
uint64_t offset;
uint32_t n_sectors;
+ g_free(block);
+ header = g_malloc(sizeof(*header));
+
logout("now writing modified header\n");
assert(VDI_IS_ALLOCATED(bmap_first));
*header = s->header;
vdi_header_to_le(header);
- ret = bdrv_write(bs->file, 0, block, 1);
- g_free(block);
- block = NULL;
+ ret = bdrv_pwrite(bs->file, 0, header, sizeof(*header));
+ g_free(header);
if (ret < 0) {
return ret;
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,
goto exit;
}
- blk = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
- ret = blk_insert_bs(blk, bs_file, errp);
- if (ret < 0) {
+ blk = blk_new_with_bs(bs_file, BLK_PERM_WRITE | BLK_PERM_RESIZE,
+ BLK_PERM_ALL, errp);
+ if (!blk) {
+ ret = -EPERM;
goto exit;
}
}
if (image_type == VDI_TYPE_STATIC) {
- ret = blk_truncate(blk, offset + blocks * block_size,
- PREALLOC_MODE_OFF, errp);
+ ret = blk_truncate(blk, offset + blocks * block_size, false,
+ PREALLOC_MODE_OFF, 0, errp);
if (ret < 0) {
error_prepend(errp, "Failed to statically allocate file");
goto exit;
return vdi_co_do_create(create_options, DEFAULT_CLUSTER_SIZE, errp);
}
-static int coroutine_fn vdi_co_create_opts(const char *filename, QemuOpts *opts,
+static int coroutine_fn vdi_co_create_opts(BlockDriver *drv,
+ const char *filename,
+ QemuOpts *opts,
Error **errp)
{
QDict *qdict = NULL;
uint64_t block_size = DEFAULT_CLUSTER_SIZE;
bool is_static = false;
Visitor *v;
- Error *local_err = NULL;
int ret;
/* Parse options and convert legacy syntax.
ret = -EINVAL;
goto done;
}
- visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err);
+ visit_type_BlockdevCreateOptions(v, NULL, &create_options, errp);
visit_free(v);
-
- if (local_err) {
- error_propagate(errp, local_err);
+ if (!create_options) {
ret = -EINVAL;
goto done;
}
error_free(s->migration_blocker);
}
+static int vdi_has_zero_init(BlockDriverState *bs)
+{
+ BDRVVdiState *s = bs->opaque;
+
+ if (s->header.image_type == VDI_TYPE_STATIC) {
+ return bdrv_has_zero_init(bs->file->bs);
+ } else {
+ return 1;
+ }
+}
+
static QemuOptsList vdi_create_opts = {
.name = "vdi-create-opts",
.head = QTAILQ_HEAD_INITIALIZER(vdi_create_opts.head),
.bdrv_open = vdi_open,
.bdrv_close = vdi_close,
.bdrv_reopen_prepare = vdi_reopen_prepare,
- .bdrv_child_perm = bdrv_format_default_perms,
+ .bdrv_child_perm = bdrv_default_perms,
.bdrv_co_create = vdi_co_create,
.bdrv_co_create_opts = vdi_co_create_opts,
- .bdrv_has_zero_init = bdrv_has_zero_init_1,
+ .bdrv_has_zero_init = vdi_has_zero_init,
.bdrv_co_block_status = vdi_co_block_status,
.bdrv_make_empty = vdi_make_empty,
.bdrv_get_info = vdi_get_info,
+ .is_format = true,
.create_opts = &vdi_create_opts,
.bdrv_co_check = vdi_co_check,
};