Loading block/vpc.c +115 −37 Original line number Diff line number Diff line Loading @@ -32,6 +32,9 @@ #include "migration/blocker.h" #include "qemu/bswap.h" #include "qemu/uuid.h" #include "qapi/qmp/qdict.h" #include "qapi/qobject-input-visitor.h" #include "qapi/qapi-visit-block-core.h" /**************************************************************/ Loading Loading @@ -166,6 +169,8 @@ static QemuOptsList vpc_runtime_opts = { } }; static QemuOptsList vpc_create_opts; static uint32_t vpc_checksum(uint8_t* buf, size_t size) { uint32_t res = 0; Loading Loading @@ -897,12 +902,15 @@ static int create_fixed_disk(BlockBackend *blk, uint8_t *buf, return ret; } static int coroutine_fn vpc_co_create_opts(const char *filename, QemuOpts *opts, static int coroutine_fn vpc_co_create(BlockdevCreateOptions *opts, Error **errp) { BlockdevCreateOptionsVpc *vpc_opts; BlockBackend *blk = NULL; BlockDriverState *bs = NULL; uint8_t buf[1024]; VHDFooter *footer = (VHDFooter *) buf; char *disk_type_param; int i; uint16_t cyls = 0; uint8_t heads = 0; Loading @@ -911,45 +919,38 @@ static int coroutine_fn vpc_co_create_opts(const char *filename, QemuOpts *opts, int64_t total_size; int disk_type; int ret = -EIO; bool force_size; Error *local_err = NULL; BlockBackend *blk = NULL; /* Read out options */ total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0), BDRV_SECTOR_SIZE); 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 { error_setg(errp, "Invalid disk type, %s", disk_type_param); ret = -EINVAL; goto out; assert(opts->driver == BLOCKDEV_DRIVER_VPC); vpc_opts = &opts->u.vpc; /* Validate options and set default values */ total_size = vpc_opts->size; if (!vpc_opts->has_subformat) { vpc_opts->subformat = BLOCKDEV_VPC_SUBFORMAT_DYNAMIC; } } else { switch (vpc_opts->subformat) { case BLOCKDEV_VPC_SUBFORMAT_DYNAMIC: disk_type = VHD_DYNAMIC; break; case BLOCKDEV_VPC_SUBFORMAT_FIXED: disk_type = VHD_FIXED; break; default: g_assert_not_reached(); } force_size = qemu_opt_get_bool_del(opts, VPC_OPT_FORCE_SIZE, false); ret = bdrv_create_file(filename, opts, &local_err); if (ret < 0) { error_propagate(errp, local_err); goto out; /* Create BlockBackend to write to the image */ bs = bdrv_open_blockdev_ref(vpc_opts->file, errp); if (bs == NULL) { return -EIO; } blk = blk_new_open(filename, NULL, NULL, BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, &local_err); if (blk == NULL) { error_propagate(errp, local_err); ret = -EIO; blk = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL); ret = blk_insert_bs(blk, bs, errp); if (ret < 0) { goto out; } blk_set_allow_write_beyond_eof(blk, true); /* Loading @@ -961,7 +962,7 @@ static int coroutine_fn vpc_co_create_opts(const char *filename, QemuOpts *opts, * we set the geometry to 65535 x 16 x 255 (CxHxS) sectors and use * the image size from the VHD footer to calculate total_sectors. */ if (force_size) { if (vpc_opts->force_size) { /* This will force the use of total_size for sector count, below */ cyls = VHD_CHS_MAX_C; heads = VHD_CHS_MAX_H; Loading Loading @@ -990,7 +991,7 @@ static int coroutine_fn vpc_co_create_opts(const char *filename, QemuOpts *opts, memset(buf, 0, 1024); memcpy(footer->creator, "conectix", 8); if (force_size) { if (vpc_opts->force_size) { memcpy(footer->creator_app, "qem2", 4); } else { memcpy(footer->creator_app, "qemu", 4); Loading Loading @@ -1032,10 +1033,86 @@ static int coroutine_fn vpc_co_create_opts(const char *filename, QemuOpts *opts, out: blk_unref(blk); g_free(disk_type_param); bdrv_unref(bs); return ret; } static int coroutine_fn vpc_co_create_opts(const char *filename, QemuOpts *opts, Error **errp) { BlockdevCreateOptions *create_options = NULL; QDict *qdict = NULL; QObject *qobj; Visitor *v; BlockDriverState *bs = NULL; Error *local_err = NULL; int ret; static const QDictRenames opt_renames[] = { { VPC_OPT_FORCE_SIZE, "force-size" }, { NULL, NULL }, }; /* Parse options and convert legacy syntax */ qdict = qemu_opts_to_qdict_filtered(opts, NULL, &vpc_create_opts, true); if (!qdict_rename_keys(qdict, opt_renames, errp)) { ret = -EINVAL; goto fail; } /* Create and open the file (protocol layer) */ ret = bdrv_create_file(filename, opts, &local_err); if (ret < 0) { error_propagate(errp, local_err); goto fail; } bs = bdrv_open(filename, NULL, NULL, BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp); if (bs == NULL) { ret = -EIO; goto fail; } /* Now get the QAPI type BlockdevCreateOptions */ qdict_put_str(qdict, "driver", "vpc"); qdict_put_str(qdict, "file", bs->node_name); qobj = qdict_crumple(qdict, errp); QDECREF(qdict); qdict = qobject_to_qdict(qobj); if (qdict == NULL) { ret = -EINVAL; goto fail; } v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err); visit_free(v); if (local_err) { error_propagate(errp, local_err); ret = -EINVAL; goto fail; } /* Silently round up size */ assert(create_options->driver == BLOCKDEV_DRIVER_VPC); create_options->u.vpc.size = ROUND_UP(create_options->u.vpc.size, BDRV_SECTOR_SIZE); /* Create the vpc image (format layer) */ ret = vpc_co_create(create_options, errp); fail: QDECREF(qdict); bdrv_unref(bs); qapi_free_BlockdevCreateOptions(create_options); return ret; } static int vpc_has_zero_init(BlockDriverState *bs) { BDRVVPCState *s = bs->opaque; Loading Loading @@ -1096,6 +1173,7 @@ static BlockDriver bdrv_vpc = { .bdrv_close = vpc_close, .bdrv_reopen_prepare = vpc_reopen_prepare, .bdrv_child_perm = bdrv_format_default_perms, .bdrv_co_create = vpc_co_create, .bdrv_co_create_opts = vpc_co_create_opts, .bdrv_co_preadv = vpc_co_preadv, Loading qapi/block-core.json +32 −1 Original line number Diff line number Diff line Loading @@ -3882,6 +3882,37 @@ '*subformat': 'BlockdevVhdxSubformat', '*block-state-zero': 'bool' } } ## # @BlockdevVpcSubformat: # # @dynamic: Growing image file # @fixed: Preallocated fixed-size image file # # Since: 2.12 ## { 'enum': 'BlockdevVpcSubformat', 'data': [ 'dynamic', 'fixed' ] } ## # @BlockdevCreateOptionsVpc: # # Driver specific image creation options for vpc (VHD). # # @file Node to create the image format on # @size Size of the virtual disk in bytes # @subformat vhdx subformat (default: dynamic) # @force-size Force use of the exact byte size instead of rounding to the # next size that can be represented in CHS geometry # (default: false) # # Since: 2.12 ## { 'struct': 'BlockdevCreateOptionsVpc', 'data': { 'file': 'BlockdevRef', 'size': 'size', '*subformat': 'BlockdevVpcSubformat', '*force-size': 'bool' } } ## # @BlockdevCreateNotSupported: # Loading Loading @@ -3939,7 +3970,7 @@ 'vdi': 'BlockdevCreateOptionsVdi', 'vhdx': 'BlockdevCreateOptionsVhdx', 'vmdk': 'BlockdevCreateNotSupported', 'vpc': 'BlockdevCreateNotSupported', 'vpc': 'BlockdevCreateOptionsVpc', 'vvfat': 'BlockdevCreateNotSupported', 'vxhs': 'BlockdevCreateNotSupported' } } Loading Loading
block/vpc.c +115 −37 Original line number Diff line number Diff line Loading @@ -32,6 +32,9 @@ #include "migration/blocker.h" #include "qemu/bswap.h" #include "qemu/uuid.h" #include "qapi/qmp/qdict.h" #include "qapi/qobject-input-visitor.h" #include "qapi/qapi-visit-block-core.h" /**************************************************************/ Loading Loading @@ -166,6 +169,8 @@ static QemuOptsList vpc_runtime_opts = { } }; static QemuOptsList vpc_create_opts; static uint32_t vpc_checksum(uint8_t* buf, size_t size) { uint32_t res = 0; Loading Loading @@ -897,12 +902,15 @@ static int create_fixed_disk(BlockBackend *blk, uint8_t *buf, return ret; } static int coroutine_fn vpc_co_create_opts(const char *filename, QemuOpts *opts, static int coroutine_fn vpc_co_create(BlockdevCreateOptions *opts, Error **errp) { BlockdevCreateOptionsVpc *vpc_opts; BlockBackend *blk = NULL; BlockDriverState *bs = NULL; uint8_t buf[1024]; VHDFooter *footer = (VHDFooter *) buf; char *disk_type_param; int i; uint16_t cyls = 0; uint8_t heads = 0; Loading @@ -911,45 +919,38 @@ static int coroutine_fn vpc_co_create_opts(const char *filename, QemuOpts *opts, int64_t total_size; int disk_type; int ret = -EIO; bool force_size; Error *local_err = NULL; BlockBackend *blk = NULL; /* Read out options */ total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0), BDRV_SECTOR_SIZE); 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 { error_setg(errp, "Invalid disk type, %s", disk_type_param); ret = -EINVAL; goto out; assert(opts->driver == BLOCKDEV_DRIVER_VPC); vpc_opts = &opts->u.vpc; /* Validate options and set default values */ total_size = vpc_opts->size; if (!vpc_opts->has_subformat) { vpc_opts->subformat = BLOCKDEV_VPC_SUBFORMAT_DYNAMIC; } } else { switch (vpc_opts->subformat) { case BLOCKDEV_VPC_SUBFORMAT_DYNAMIC: disk_type = VHD_DYNAMIC; break; case BLOCKDEV_VPC_SUBFORMAT_FIXED: disk_type = VHD_FIXED; break; default: g_assert_not_reached(); } force_size = qemu_opt_get_bool_del(opts, VPC_OPT_FORCE_SIZE, false); ret = bdrv_create_file(filename, opts, &local_err); if (ret < 0) { error_propagate(errp, local_err); goto out; /* Create BlockBackend to write to the image */ bs = bdrv_open_blockdev_ref(vpc_opts->file, errp); if (bs == NULL) { return -EIO; } blk = blk_new_open(filename, NULL, NULL, BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, &local_err); if (blk == NULL) { error_propagate(errp, local_err); ret = -EIO; blk = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL); ret = blk_insert_bs(blk, bs, errp); if (ret < 0) { goto out; } blk_set_allow_write_beyond_eof(blk, true); /* Loading @@ -961,7 +962,7 @@ static int coroutine_fn vpc_co_create_opts(const char *filename, QemuOpts *opts, * we set the geometry to 65535 x 16 x 255 (CxHxS) sectors and use * the image size from the VHD footer to calculate total_sectors. */ if (force_size) { if (vpc_opts->force_size) { /* This will force the use of total_size for sector count, below */ cyls = VHD_CHS_MAX_C; heads = VHD_CHS_MAX_H; Loading Loading @@ -990,7 +991,7 @@ static int coroutine_fn vpc_co_create_opts(const char *filename, QemuOpts *opts, memset(buf, 0, 1024); memcpy(footer->creator, "conectix", 8); if (force_size) { if (vpc_opts->force_size) { memcpy(footer->creator_app, "qem2", 4); } else { memcpy(footer->creator_app, "qemu", 4); Loading Loading @@ -1032,10 +1033,86 @@ static int coroutine_fn vpc_co_create_opts(const char *filename, QemuOpts *opts, out: blk_unref(blk); g_free(disk_type_param); bdrv_unref(bs); return ret; } static int coroutine_fn vpc_co_create_opts(const char *filename, QemuOpts *opts, Error **errp) { BlockdevCreateOptions *create_options = NULL; QDict *qdict = NULL; QObject *qobj; Visitor *v; BlockDriverState *bs = NULL; Error *local_err = NULL; int ret; static const QDictRenames opt_renames[] = { { VPC_OPT_FORCE_SIZE, "force-size" }, { NULL, NULL }, }; /* Parse options and convert legacy syntax */ qdict = qemu_opts_to_qdict_filtered(opts, NULL, &vpc_create_opts, true); if (!qdict_rename_keys(qdict, opt_renames, errp)) { ret = -EINVAL; goto fail; } /* Create and open the file (protocol layer) */ ret = bdrv_create_file(filename, opts, &local_err); if (ret < 0) { error_propagate(errp, local_err); goto fail; } bs = bdrv_open(filename, NULL, NULL, BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp); if (bs == NULL) { ret = -EIO; goto fail; } /* Now get the QAPI type BlockdevCreateOptions */ qdict_put_str(qdict, "driver", "vpc"); qdict_put_str(qdict, "file", bs->node_name); qobj = qdict_crumple(qdict, errp); QDECREF(qdict); qdict = qobject_to_qdict(qobj); if (qdict == NULL) { ret = -EINVAL; goto fail; } v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err); visit_free(v); if (local_err) { error_propagate(errp, local_err); ret = -EINVAL; goto fail; } /* Silently round up size */ assert(create_options->driver == BLOCKDEV_DRIVER_VPC); create_options->u.vpc.size = ROUND_UP(create_options->u.vpc.size, BDRV_SECTOR_SIZE); /* Create the vpc image (format layer) */ ret = vpc_co_create(create_options, errp); fail: QDECREF(qdict); bdrv_unref(bs); qapi_free_BlockdevCreateOptions(create_options); return ret; } static int vpc_has_zero_init(BlockDriverState *bs) { BDRVVPCState *s = bs->opaque; Loading Loading @@ -1096,6 +1173,7 @@ static BlockDriver bdrv_vpc = { .bdrv_close = vpc_close, .bdrv_reopen_prepare = vpc_reopen_prepare, .bdrv_child_perm = bdrv_format_default_perms, .bdrv_co_create = vpc_co_create, .bdrv_co_create_opts = vpc_co_create_opts, .bdrv_co_preadv = vpc_co_preadv, Loading
qapi/block-core.json +32 −1 Original line number Diff line number Diff line Loading @@ -3882,6 +3882,37 @@ '*subformat': 'BlockdevVhdxSubformat', '*block-state-zero': 'bool' } } ## # @BlockdevVpcSubformat: # # @dynamic: Growing image file # @fixed: Preallocated fixed-size image file # # Since: 2.12 ## { 'enum': 'BlockdevVpcSubformat', 'data': [ 'dynamic', 'fixed' ] } ## # @BlockdevCreateOptionsVpc: # # Driver specific image creation options for vpc (VHD). # # @file Node to create the image format on # @size Size of the virtual disk in bytes # @subformat vhdx subformat (default: dynamic) # @force-size Force use of the exact byte size instead of rounding to the # next size that can be represented in CHS geometry # (default: false) # # Since: 2.12 ## { 'struct': 'BlockdevCreateOptionsVpc', 'data': { 'file': 'BlockdevRef', 'size': 'size', '*subformat': 'BlockdevVpcSubformat', '*force-size': 'bool' } } ## # @BlockdevCreateNotSupported: # Loading Loading @@ -3939,7 +3970,7 @@ 'vdi': 'BlockdevCreateOptionsVdi', 'vhdx': 'BlockdevCreateOptionsVhdx', 'vmdk': 'BlockdevCreateNotSupported', 'vpc': 'BlockdevCreateNotSupported', 'vpc': 'BlockdevCreateOptionsVpc', 'vvfat': 'BlockdevCreateNotSupported', 'vxhs': 'BlockdevCreateNotSupported' } } Loading