#include "qemu-common.h"
#include "block_int.h"
#include "module.h"
+#include "migration.h"
/**************************************************************/
};
typedef struct BDRVVPCState {
+ CoMutex lock;
uint8_t footer_buf[HEADER_SIZE];
uint64_t free_data_block_offset;
int max_table_entries;
uint64_t last_bitmap;
#endif
+
+ Error *migration_blocker;
} BDRVVPCState;
static uint32_t vpc_checksum(uint8_t* buf, size_t size)
struct vhd_dyndisk_header* dyndisk_header;
uint8_t buf[HEADER_SIZE];
uint32_t checksum;
+ int err = -1;
if (bdrv_pread(bs->file, 0, s->footer_buf, HEADER_SIZE) != HEADER_SIZE)
goto fail;
bs->total_sectors = (int64_t)
be16_to_cpu(footer->cyls) * footer->heads * footer->secs_per_cyl;
+ if (bs->total_sectors >= 65535 * 16 * 255) {
+ err = -EFBIG;
+ goto fail;
+ }
+
if (bdrv_pread(bs->file, be64_to_cpu(footer->data_offset), buf, HEADER_SIZE)
!= HEADER_SIZE)
goto fail;
s->bitmap_size = ((s->block_size / (8 * 512)) + 511) & ~511;
s->max_table_entries = be32_to_cpu(dyndisk_header->max_table_entries);
- s->pagetable = qemu_malloc(s->max_table_entries * 4);
+ 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->last_bitmap_offset = (int64_t) -1;
#ifdef CACHE
- s->pageentry_u8 = qemu_malloc(512);
+ s->pageentry_u8 = g_malloc(512);
s->pageentry_u32 = s->pageentry_u8;
s->pageentry_u16 = s->pageentry_u8;
s->last_pagetable = -1;
#endif
+ qemu_co_mutex_init(&s->lock);
+
+ /* Disable migration when VHD images are used */
+ error_set(&s->migration_blocker,
+ QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
+ "vpc", bs->device_name, "live migration");
+ migrate_add_blocker(s->migration_blocker);
+
return 0;
fail:
- return -1;
+ return err;
}
/*
return 0;
}
+static coroutine_fn int vpc_co_read(BlockDriverState *bs, int64_t sector_num,
+ uint8_t *buf, int nb_sectors)
+{
+ int ret;
+ BDRVVPCState *s = bs->opaque;
+ qemu_co_mutex_lock(&s->lock);
+ ret = vpc_read(bs, sector_num, buf, nb_sectors);
+ qemu_co_mutex_unlock(&s->lock);
+ return ret;
+}
+
static int vpc_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
return 0;
}
-static int vpc_flush(BlockDriverState *bs)
+static coroutine_fn int vpc_co_write(BlockDriverState *bs, int64_t sector_num,
+ const uint8_t *buf, int nb_sectors)
+{
+ int ret;
+ BDRVVPCState *s = bs->opaque;
+ qemu_co_mutex_lock(&s->lock);
+ ret = vpc_write(bs, sector_num, buf, nb_sectors);
+ qemu_co_mutex_unlock(&s->lock);
+ return ret;
+}
+
+static coroutine_fn int vpc_co_flush(BlockDriverState *bs)
{
- return bdrv_flush(bs->file);
+ return bdrv_co_flush(bs->file);
}
/*
int ret = -EIO;
// Read out options
- while (options && options->name) {
- if (!strcmp(options->name, "size")) {
- total_sectors = options->value.n / 512;
- }
- options++;
- }
+ total_sectors = get_option_parameter(options, BLOCK_OPT_SIZE)->value.n /
+ BDRV_SECTOR_SIZE;
// Create the file
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
memcpy(dyndisk_header->magic, "cxsparse", 8);
- dyndisk_header->data_offset = be64_to_cpu(0xFFFFFFFF);
+ /*
+ * Note: The spec is actually wrong here for data_offset, it says
+ * 0xFFFFFFFF, but MS tools expect all 64 bits to be set.
+ */
+ dyndisk_header->data_offset = be64_to_cpu(0xFFFFFFFFFFFFFFFFULL);
dyndisk_header->table_offset = be64_to_cpu(3 * 512);
dyndisk_header->version = be32_to_cpu(0x00010000);
dyndisk_header->block_size = be32_to_cpu(block_size);
static void vpc_close(BlockDriverState *bs)
{
BDRVVPCState *s = bs->opaque;
- qemu_free(s->pagetable);
+ g_free(s->pagetable);
#ifdef CACHE
- qemu_free(s->pageentry_u8);
+ g_free(s->pageentry_u8);
#endif
+
+ migrate_del_blocker(s->migration_blocker);
+ error_free(s->migration_blocker);
}
static QEMUOptionParameter vpc_create_options[] = {
static BlockDriver bdrv_vpc = {
.format_name = "vpc",
.instance_size = sizeof(BDRVVPCState),
+
.bdrv_probe = vpc_probe,
.bdrv_open = vpc_open,
- .bdrv_read = vpc_read,
- .bdrv_write = vpc_write,
- .bdrv_flush = vpc_flush,
.bdrv_close = vpc_close,
.bdrv_create = vpc_create,
+ .bdrv_read = vpc_co_read,
+ .bdrv_write = vpc_co_write,
+ .bdrv_co_flush_to_disk = vpc_co_flush,
+
.create_options = vpc_create_options,
};