#define VHD_TIMESTAMP_BASE 946684800
// always big-endian
-struct vhd_footer {
+typedef struct vhd_footer {
char creator[8]; // "conectix"
uint32_t features;
uint32_t version;
uint8_t uuid[16];
uint8_t in_saved_state;
-};
+} QEMU_PACKED VHDFooter;
-struct vhd_dyndisk_header {
+typedef struct vhd_dyndisk_header {
char magic[8]; // "cxsparse"
// Offset of next header structure, 0xFFFFFFFF if none
uint32_t reserved;
uint64_t data_offset;
} parent_locator[8];
-};
+} QEMU_PACKED VHDDynDiskHeader;
typedef struct BDRVVPCState {
CoMutex lock;
return 0;
}
-static int vpc_open(BlockDriverState *bs, int flags)
+static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
+ Error **errp)
{
BDRVVPCState *s = bs->opaque;
int i;
- struct vhd_footer* footer;
- struct vhd_dyndisk_header* dyndisk_header;
+ VHDFooter *footer;
+ VHDDynDiskHeader *dyndisk_header;
uint8_t buf[HEADER_SIZE];
uint32_t checksum;
- int err = -1;
int disk_type = VHD_DYNAMIC;
+ int ret;
- if (bdrv_pread(bs->file, 0, s->footer_buf, HEADER_SIZE) != HEADER_SIZE)
+ ret = bdrv_pread(bs->file, 0, s->footer_buf, HEADER_SIZE);
+ if (ret < 0) {
goto fail;
+ }
- footer = (struct vhd_footer*) s->footer_buf;
+ footer = (VHDFooter *) s->footer_buf;
if (strncmp(footer->creator, "conectix", 8)) {
int64_t offset = bdrv_getlength(bs->file);
- if (offset < HEADER_SIZE) {
+ if (offset < 0) {
+ ret = offset;
+ goto fail;
+ } else if (offset < HEADER_SIZE) {
+ ret = -EINVAL;
goto fail;
}
+
/* If a fixed disk, the footer is found only at the end of the file */
- if (bdrv_pread(bs->file, offset-HEADER_SIZE, s->footer_buf, HEADER_SIZE)
- != HEADER_SIZE) {
+ ret = bdrv_pread(bs->file, offset-HEADER_SIZE, s->footer_buf,
+ HEADER_SIZE);
+ if (ret < 0) {
goto fail;
}
if (strncmp(footer->creator, "conectix", 8)) {
+ ret = -EMEDIUMTYPE;
goto fail;
}
disk_type = VHD_FIXED;
/* Allow a maximum disk size of approximately 2 TB */
if (bs->total_sectors >= 65535LL * 255 * 255) {
- err = -EFBIG;
+ ret = -EFBIG;
goto fail;
}
if (disk_type == VHD_DYNAMIC) {
- if (bdrv_pread(bs->file, be64_to_cpu(footer->data_offset), buf,
- HEADER_SIZE) != HEADER_SIZE) {
+ ret = bdrv_pread(bs->file, be64_to_cpu(footer->data_offset), buf,
+ HEADER_SIZE);
+ if (ret < 0) {
goto fail;
}
- dyndisk_header = (struct vhd_dyndisk_header *) buf;
+ dyndisk_header = (VHDDynDiskHeader *) buf;
if (strncmp(dyndisk_header->magic, "cxsparse", 8)) {
+ ret = -EINVAL;
goto fail;
}
s->pagetable = g_malloc(s->max_table_entries * 4);
s->bat_offset = be64_to_cpu(dyndisk_header->table_offset);
- if (bdrv_pread(bs->file, s->bat_offset, s->pagetable,
- s->max_table_entries * 4) != s->max_table_entries * 4) {
+
+ ret = bdrv_pread(bs->file, s->bat_offset, s->pagetable,
+ s->max_table_entries * 4);
+ if (ret < 0) {
goto fail;
}
migrate_add_blocker(s->migration_blocker);
return 0;
- fail:
- return err;
+
+fail:
+ g_free(s->pagetable);
+#ifdef CACHE
+ g_free(s->pageentry_u8);
+#endif
+ return ret;
}
static int vpc_reopen_prepare(BDRVReopenState *state,
int ret;
int64_t offset;
int64_t sectors, sectors_per_block;
- struct vhd_footer *footer = (struct vhd_footer *) s->footer_buf;
+ VHDFooter *footer = (VHDFooter *) s->footer_buf;
if (cpu_to_be32(footer->type) == VHD_FIXED) {
return bdrv_read(bs->file, sector_num, buf, nb_sectors);
int64_t offset;
int64_t sectors, sectors_per_block;
int ret;
- struct vhd_footer *footer = (struct vhd_footer *) s->footer_buf;
+ VHDFooter *footer = (VHDFooter *) s->footer_buf;
if (cpu_to_be32(footer->type) == VHD_FIXED) {
return bdrv_write(bs->file, sector_num, buf, nb_sectors);
static int create_dynamic_disk(int fd, uint8_t *buf, int64_t total_sectors)
{
- struct vhd_dyndisk_header* dyndisk_header =
- (struct vhd_dyndisk_header*) buf;
+ VHDDynDiskHeader *dyndisk_header =
+ (VHDDynDiskHeader *) buf;
size_t block_size, num_bat_entries;
int i;
int ret = -EIO;
return ret;
}
-static int vpc_create(const char *filename, QEMUOptionParameter *options)
+static int vpc_create(const char *filename, QEMUOptionParameter *options,
+ Error **errp)
{
uint8_t buf[1024];
- struct vhd_footer *footer = (struct vhd_footer *) buf;
+ VHDFooter *footer = (VHDFooter *) buf;
QEMUOptionParameter *disk_type_param;
int fd, i;
uint16_t cyls = 0;
return ret;
}
+static int vpc_has_zero_init(BlockDriverState *bs)
+{
+ BDRVVPCState *s = bs->opaque;
+ VHDFooter *footer = (VHDFooter *) s->footer_buf;
+
+ if (cpu_to_be32(footer->type) == VHD_FIXED) {
+ return bdrv_has_zero_init(bs->file);
+ } else {
+ return 1;
+ }
+}
+
static void vpc_close(BlockDriverState *bs)
{
BDRVVPCState *s = bs->opaque;
.format_name = "vpc",
.instance_size = sizeof(BDRVVPCState),
- .bdrv_probe = vpc_probe,
- .bdrv_open = vpc_open,
- .bdrv_close = vpc_close,
- .bdrv_reopen_prepare = vpc_reopen_prepare,
- .bdrv_create = vpc_create,
+ .bdrv_probe = vpc_probe,
+ .bdrv_open = vpc_open,
+ .bdrv_close = vpc_close,
+ .bdrv_reopen_prepare = vpc_reopen_prepare,
+ .bdrv_create = vpc_create,
.bdrv_read = vpc_co_read,
.bdrv_write = vpc_co_write,
- .create_options = vpc_create_options,
+ .create_options = vpc_create_options,
+ .bdrv_has_zero_init = vpc_has_zero_init,
};
static void bdrv_vpc_init(void)