vdi: Pull option parsing from vdi_co_create
In preparation of QAPI-fying VDI image creation, we have to create a BlockdevCreateOptionsVdi type which is received by a (future) vdi_co_create(). vdi_co_create_opts() now converts the QemuOpts object into such a BlockdevCreateOptionsVdi object. The protocol-layer file is still created in vdi_co_do_create() (and BlockdevCreateOptionsVdi.file is set to an empty string), but that will be addressed by a follow-up patch. Note that cluster-size is not part of the QAPI schema because it is not supported by default. Signed-off-by: Max Reitz <mreitz@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
d06195e6a6
commit
49858b5098
91
block/vdi.c
91
block/vdi.c
@ -51,6 +51,9 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qapi/qobject-input-visitor.h"
|
||||
#include "qapi/qapi-visit-block-core.h"
|
||||
#include "block/block_int.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "qemu/module.h"
|
||||
@ -140,6 +143,8 @@
|
||||
#define VDI_DISK_SIZE_MAX ((uint64_t)VDI_BLOCKS_IN_IMAGE_MAX * \
|
||||
(uint64_t)DEFAULT_CLUSTER_SIZE)
|
||||
|
||||
static QemuOptsList vdi_create_opts;
|
||||
|
||||
typedef struct {
|
||||
char text[0x40];
|
||||
uint32_t signature;
|
||||
@ -716,13 +721,14 @@ nonallocating_write:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int coroutine_fn vdi_co_create_opts(const char *filename, QemuOpts *opts,
|
||||
Error **errp)
|
||||
static int coroutine_fn vdi_co_do_create(const char *filename,
|
||||
QemuOpts *file_opts,
|
||||
BlockdevCreateOptionsVdi *vdi_opts,
|
||||
size_t block_size, Error **errp)
|
||||
{
|
||||
int ret = 0;
|
||||
uint64_t bytes = 0;
|
||||
uint32_t blocks;
|
||||
size_t block_size = DEFAULT_CLUSTER_SIZE;
|
||||
uint32_t image_type = VDI_TYPE_DYNAMIC;
|
||||
VdiHeader header;
|
||||
size_t i;
|
||||
@ -735,18 +741,25 @@ static int coroutine_fn vdi_co_create_opts(const char *filename, QemuOpts *opts,
|
||||
logout("\n");
|
||||
|
||||
/* Read out options. */
|
||||
bytes = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
|
||||
BDRV_SECTOR_SIZE);
|
||||
#if defined(CONFIG_VDI_BLOCK_SIZE)
|
||||
/* TODO: Additional checks (SECTOR_SIZE * 2^n, ...). */
|
||||
block_size = qemu_opt_get_size_del(opts,
|
||||
BLOCK_OPT_CLUSTER_SIZE,
|
||||
DEFAULT_CLUSTER_SIZE);
|
||||
#endif
|
||||
#if defined(CONFIG_VDI_STATIC_IMAGE)
|
||||
if (qemu_opt_get_bool_del(opts, BLOCK_OPT_STATIC, false)) {
|
||||
bytes = vdi_opts->size;
|
||||
if (vdi_opts->q_static) {
|
||||
image_type = VDI_TYPE_STATIC;
|
||||
}
|
||||
#ifndef CONFIG_VDI_STATIC_IMAGE
|
||||
if (image_type == VDI_TYPE_STATIC) {
|
||||
ret = -ENOTSUP;
|
||||
error_setg(errp, "Statically allocated images cannot be created in "
|
||||
"this build");
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
#ifndef CONFIG_VDI_BLOCK_SIZE
|
||||
if (block_size != DEFAULT_CLUSTER_SIZE) {
|
||||
ret = -ENOTSUP;
|
||||
error_setg(errp,
|
||||
"A non-default cluster size is not supported in this build");
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (bytes > VDI_DISK_SIZE_MAX) {
|
||||
@ -757,7 +770,7 @@ static int coroutine_fn vdi_co_create_opts(const char *filename, QemuOpts *opts,
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = bdrv_create_file(filename, opts, &local_err);
|
||||
ret = bdrv_create_file(filename, file_opts, &local_err);
|
||||
if (ret < 0) {
|
||||
error_propagate(errp, local_err);
|
||||
goto exit;
|
||||
@ -847,6 +860,56 @@ exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int coroutine_fn vdi_co_create_opts(const char *filename, QemuOpts *opts,
|
||||
Error **errp)
|
||||
{
|
||||
QDict *qdict = NULL;
|
||||
BlockdevCreateOptionsVdi *create_options = NULL;
|
||||
uint64_t block_size = DEFAULT_CLUSTER_SIZE;
|
||||
Visitor *v;
|
||||
Error *local_err = NULL;
|
||||
int ret;
|
||||
|
||||
/* Since CONFIG_VDI_BLOCK_SIZE is disabled by default,
|
||||
* cluster-size is not part of the QAPI schema; therefore we have
|
||||
* to parse it before creating the QAPI object. */
|
||||
#if defined(CONFIG_VDI_BLOCK_SIZE)
|
||||
block_size = qemu_opt_get_size_del(opts,
|
||||
BLOCK_OPT_CLUSTER_SIZE,
|
||||
DEFAULT_CLUSTER_SIZE);
|
||||
if (block_size < BDRV_SECTOR_SIZE || block_size > UINT32_MAX ||
|
||||
!is_power_of_2(block_size))
|
||||
{
|
||||
error_setg(errp, "Invalid cluster size");
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
|
||||
qdict = qemu_opts_to_qdict_filtered(opts, NULL, &vdi_create_opts, true);
|
||||
|
||||
qdict_put_str(qdict, "file", ""); /* FIXME */
|
||||
|
||||
/* Get the QAPI object */
|
||||
v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
|
||||
visit_type_BlockdevCreateOptionsVdi(v, NULL, &create_options, &local_err);
|
||||
visit_free(v);
|
||||
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
create_options->size = ROUND_UP(create_options->size, BDRV_SECTOR_SIZE);
|
||||
|
||||
ret = vdi_co_do_create(filename, opts, create_options, block_size, errp);
|
||||
done:
|
||||
QDECREF(qdict);
|
||||
qapi_free_BlockdevCreateOptionsVdi(create_options);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void vdi_close(BlockDriverState *bs)
|
||||
{
|
||||
BDRVVdiState *s = bs->opaque;
|
||||
|
@ -3768,6 +3768,24 @@
|
||||
'data': { 'location': 'BlockdevOptionsSsh',
|
||||
'size': 'size' } }
|
||||
|
||||
##
|
||||
# @BlockdevCreateOptionsVdi:
|
||||
#
|
||||
# Driver specific image creation options for VDI.
|
||||
#
|
||||
# @file Node to create the image format on
|
||||
# @size Size of the virtual disk in bytes
|
||||
# @static Whether to create a statically (true) or
|
||||
# dynamically (false) allocated image
|
||||
# (default: false, i.e. dynamic)
|
||||
#
|
||||
# Since: 2.12
|
||||
##
|
||||
{ 'struct': 'BlockdevCreateOptionsVdi',
|
||||
'data': { 'file': 'BlockdevRef',
|
||||
'size': 'size',
|
||||
'*static': 'bool' } }
|
||||
|
||||
##
|
||||
# @BlockdevCreateNotSupported:
|
||||
#
|
||||
|
Loading…
Reference in New Issue
Block a user