@@ -786,6 +786,109 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options)
return ret;
}
+static int vpc_create_new(const char *filename, QemuOpts *opts)
+{
+ uint8_t buf[1024];
+ struct vhd_footer *footer = (struct vhd_footer *) buf;
+ char *disk_type_param = NULL;
+ int fd, i;
+ uint16_t cyls = 0;
+ uint8_t heads = 0;
+ uint8_t secs_per_cyl = 0;
+ int64_t total_sectors;
+ int64_t total_size = 0;
+ int disk_type = VHD_DYNAMIC;
+ int ret = -EIO;
+
+ /* Read out opts */
+ total_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
+ disk_type_param = qemu_opt_get_del(opts, BLOCK_OPT_SUBFMT);
+ if (disk_type_param) {
+ if (!strcmp(disk_type_param, "dynamic")) {
+ disk_type = VHD_DYNAMIC;
+ } else if (!strcmp(disk_type_param, "fixed")) {
+ disk_type = VHD_FIXED;
+ } else {
+ ret = -EINVAL;
+ goto finish;
+ }
+ }
+
+ /* Create the file */
+ fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
+ if (fd < 0) {
+ ret = -EIO;
+ goto finish;
+ }
+
+ /*
+ * Calculate matching total_size and geometry. Increase the number of
+ * sectors requested until we get enough (or fail). This ensures that
+ * qemu-img convert doesn't truncate images, but rather rounds up.
+ */
+ total_sectors = total_size / BDRV_SECTOR_SIZE;
+ for (i = 0; total_sectors > (int64_t)cyls * heads * secs_per_cyl; i++) {
+ if (calculate_geometry(total_sectors + i, &cyls, &heads,
+ &secs_per_cyl)) {
+ ret = -EFBIG;
+ goto fail;
+ }
+ }
+
+ total_sectors = (int64_t) cyls * heads * secs_per_cyl;
+
+ /* Prepare the Hard Disk Footer */
+ memset(buf, 0, 1024);
+
+ memcpy(footer->creator, "conectix", 8);
+ /* TODO Check if "qemu" creator_app is ok for VPC */
+ memcpy(footer->creator_app, "qemu", 4);
+ memcpy(footer->creator_os, "Wi2k", 4);
+
+ footer->features = be32_to_cpu(0x02);
+ footer->version = be32_to_cpu(0x00010000);
+ if (disk_type == VHD_DYNAMIC) {
+ footer->data_offset = be64_to_cpu(HEADER_SIZE);
+ } else {
+ footer->data_offset = be64_to_cpu(0xFFFFFFFFFFFFFFFFULL);
+ }
+ footer->timestamp = be32_to_cpu(time(NULL) - VHD_TIMESTAMP_BASE);
+
+ /* Version of Virtual PC 2007 */
+ footer->major = be16_to_cpu(0x0005);
+ footer->minor = be16_to_cpu(0x0003);
+ if (disk_type == VHD_DYNAMIC) {
+ footer->orig_size = be64_to_cpu(total_sectors * 512);
+ footer->size = be64_to_cpu(total_sectors * 512);
+ } else {
+ footer->orig_size = be64_to_cpu(total_size);
+ footer->size = be64_to_cpu(total_size);
+ }
+ footer->cyls = be16_to_cpu(cyls);
+ footer->heads = heads;
+ footer->secs_per_cyl = secs_per_cyl;
+
+ footer->type = be32_to_cpu(disk_type);
+
+#if defined(CONFIG_UUID)
+ uuid_generate(footer->uuid);
+#endif
+
+ footer->checksum = be32_to_cpu(vpc_checksum(buf, HEADER_SIZE));
+
+ if (disk_type == VHD_DYNAMIC) {
+ ret = create_dynamic_disk(fd, buf, total_sectors);
+ } else {
+ ret = create_fixed_disk(fd, buf, total_size);
+ }
+
+ fail:
+ qemu_close(fd);
+finish:
+ g_free(disk_type_param);
+ return ret;
+}
+
static int vpc_has_zero_init(BlockDriverState *bs)
{
BDRVVPCState *s = bs->opaque;
@@ -826,6 +929,26 @@ static QEMUOptionParameter vpc_create_options[] = {
{ NULL }
};
+static QemuOptsList vpc_create_opts = {
+ .name = "vpc-create-opts",
+ .head = QTAILQ_HEAD_INITIALIZER(vpc_create_opts.head),
+ .desc = {
+ {
+ .name = BLOCK_OPT_SIZE,
+ .type = QEMU_OPT_SIZE,
+ .help = "Virtual disk size"
+ },
+ {
+ .name = BLOCK_OPT_SUBFMT,
+ .type = QEMU_OPT_STRING,
+ .help =
+ "Type of virtual hard disk format. Supported formats are "
+ "{dynamic (default) | fixed} "
+ },
+ { /* end of list */ }
+ }
+};
+
static BlockDriver bdrv_vpc = {
.format_name = "vpc",
.instance_size = sizeof(BDRVVPCState),
@@ -835,11 +958,13 @@ static BlockDriver bdrv_vpc = {
.bdrv_close = vpc_close,
.bdrv_reopen_prepare = vpc_reopen_prepare,
.bdrv_create = vpc_create,
+ .bdrv_create_new = vpc_create_new,
.bdrv_read = vpc_co_read,
.bdrv_write = vpc_co_write,
.create_options = vpc_create_options,
+ .bdrv_create_opts = &vpc_create_opts,
.bdrv_has_zero_init = vpc_has_zero_init,
};
Signed-off-by: Dong Xu Wang <wdongxu@linux.vnet.ibm.com> --- block/vpc.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+)