qcow2.c: replace QEMUOptionParameter with QemuOpts

Signed-off-by: Dong Xu Wang <wdongxu@linux.vnet.ibm.com>
Signed-off-by: Chunyan Liu <cyliu@suse.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Chunyan Liu 2014-06-05 17:20:59 +08:00 committed by Stefan Hajnoczi
parent 74c3c19765
commit 1bd0e2d1c4
1 changed files with 139 additions and 122 deletions

View File

@ -31,6 +31,7 @@
#include "qapi/qmp/qerror.h" #include "qapi/qmp/qerror.h"
#include "qapi/qmp/qbool.h" #include "qapi/qmp/qbool.h"
#include "trace.h" #include "trace.h"
#include "qemu/option_int.h"
/* /*
Differences with QCOW: Differences with QCOW:
@ -1594,7 +1595,7 @@ static int preallocate(BlockDriverState *bs)
static int qcow2_create2(const char *filename, int64_t total_size, static int qcow2_create2(const char *filename, int64_t total_size,
const char *backing_file, const char *backing_format, const char *backing_file, const char *backing_format,
int flags, size_t cluster_size, int prealloc, int flags, size_t cluster_size, int prealloc,
QEMUOptionParameter *options, int version, QemuOpts *opts, int version,
Error **errp) Error **errp)
{ {
/* Calculate cluster_bits */ /* Calculate cluster_bits */
@ -1626,7 +1627,7 @@ static int qcow2_create2(const char *filename, int64_t total_size,
Error *local_err = NULL; Error *local_err = NULL;
int ret; int ret;
ret = bdrv_create_file(filename, options, NULL, &local_err); ret = bdrv_create_file(filename, NULL, opts, &local_err);
if (ret < 0) { if (ret < 0) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
return ret; return ret;
@ -1762,11 +1763,11 @@ out:
return ret; return ret;
} }
static int qcow2_create(const char *filename, QEMUOptionParameter *options, static int qcow2_create(const char *filename, QemuOpts *opts, Error **errp)
Error **errp)
{ {
const char *backing_file = NULL; char *backing_file = NULL;
const char *backing_fmt = NULL; char *backing_fmt = NULL;
char *buf = NULL;
uint64_t sectors = 0; uint64_t sectors = 0;
int flags = 0; int flags = 0;
size_t cluster_size = DEFAULT_CLUSTER_SIZE; size_t cluster_size = DEFAULT_CLUSTER_SIZE;
@ -1776,64 +1777,66 @@ static int qcow2_create(const char *filename, QEMUOptionParameter *options,
int ret; int ret;
/* Read out options */ /* Read out options */
while (options && options->name) { sectors = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0) / 512;
if (!strcmp(options->name, BLOCK_OPT_SIZE)) { backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE);
sectors = options->value.n / 512; backing_fmt = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FMT);
} else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) { if (qemu_opt_get_bool_del(opts, BLOCK_OPT_ENCRYPT, false)) {
backing_file = options->value.s; flags |= BLOCK_FLAG_ENCRYPT;
} else if (!strcmp(options->name, BLOCK_OPT_BACKING_FMT)) { }
backing_fmt = options->value.s; cluster_size = qemu_opt_get_size_del(opts, BLOCK_OPT_CLUSTER_SIZE,
} else if (!strcmp(options->name, BLOCK_OPT_ENCRYPT)) { DEFAULT_CLUSTER_SIZE);
flags |= options->value.n ? BLOCK_FLAG_ENCRYPT : 0; buf = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
} else if (!strcmp(options->name, BLOCK_OPT_CLUSTER_SIZE)) { if (!buf || !strcmp(buf, "off")) {
if (options->value.n) { prealloc = 0;
cluster_size = options->value.n; } else if (!strcmp(buf, "metadata")) {
} prealloc = 1;
} else if (!strcmp(options->name, BLOCK_OPT_PREALLOC)) { } else {
if (!options->value.s || !strcmp(options->value.s, "off")) { error_setg(errp, "Invalid preallocation mode: '%s'", buf);
prealloc = 0; ret = -EINVAL;
} else if (!strcmp(options->value.s, "metadata")) { goto finish;
prealloc = 1; }
} else { g_free(buf);
error_setg(errp, "Invalid preallocation mode: '%s'", buf = qemu_opt_get_del(opts, BLOCK_OPT_COMPAT_LEVEL);
options->value.s); if (!buf) {
return -EINVAL; /* keep the default */
} } else if (!strcmp(buf, "0.10")) {
} else if (!strcmp(options->name, BLOCK_OPT_COMPAT_LEVEL)) { version = 2;
if (!options->value.s) { } else if (!strcmp(buf, "1.1")) {
/* keep the default */ version = 3;
} else if (!strcmp(options->value.s, "0.10")) { } else {
version = 2; error_setg(errp, "Invalid compatibility level: '%s'", buf);
} else if (!strcmp(options->value.s, "1.1")) { ret = -EINVAL;
version = 3; goto finish;
} else { }
error_setg(errp, "Invalid compatibility level: '%s'",
options->value.s); if (qemu_opt_get_bool_del(opts, BLOCK_OPT_LAZY_REFCOUNTS, false)) {
return -EINVAL; flags |= BLOCK_FLAG_LAZY_REFCOUNTS;
}
} else if (!strcmp(options->name, BLOCK_OPT_LAZY_REFCOUNTS)) {
flags |= options->value.n ? BLOCK_FLAG_LAZY_REFCOUNTS : 0;
}
options++;
} }
if (backing_file && prealloc) { if (backing_file && prealloc) {
error_setg(errp, "Backing file and preallocation cannot be used at " error_setg(errp, "Backing file and preallocation cannot be used at "
"the same time"); "the same time");
return -EINVAL; ret = -EINVAL;
goto finish;
} }
if (version < 3 && (flags & BLOCK_FLAG_LAZY_REFCOUNTS)) { if (version < 3 && (flags & BLOCK_FLAG_LAZY_REFCOUNTS)) {
error_setg(errp, "Lazy refcounts only supported with compatibility " error_setg(errp, "Lazy refcounts only supported with compatibility "
"level 1.1 and above (use compat=1.1 or greater)"); "level 1.1 and above (use compat=1.1 or greater)");
return -EINVAL; ret = -EINVAL;
goto finish;
} }
ret = qcow2_create2(filename, sectors, backing_file, backing_fmt, flags, ret = qcow2_create2(filename, sectors, backing_file, backing_fmt, flags,
cluster_size, prealloc, options, version, &local_err); cluster_size, prealloc, opts, version, &local_err);
if (local_err) { if (local_err) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
} }
finish:
g_free(backing_file);
g_free(backing_fmt);
g_free(buf);
return ret; return ret;
} }
@ -2198,64 +2201,72 @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version)
return 0; return 0;
} }
static int qcow2_amend_options(BlockDriverState *bs, static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts)
QEMUOptionParameter *options)
{ {
BDRVQcowState *s = bs->opaque; BDRVQcowState *s = bs->opaque;
int old_version = s->qcow_version, new_version = old_version; int old_version = s->qcow_version, new_version = old_version;
uint64_t new_size = 0; uint64_t new_size = 0;
const char *backing_file = NULL, *backing_format = NULL; const char *backing_file = NULL, *backing_format = NULL;
bool lazy_refcounts = s->use_lazy_refcounts; bool lazy_refcounts = s->use_lazy_refcounts;
const char *compat = NULL;
uint64_t cluster_size = s->cluster_size;
bool encrypt;
int ret; int ret;
int i; QemuOptDesc *desc = opts->list->desc;
for (i = 0; options[i].name; i++) while (desc && desc->name) {
{ if (!qemu_opt_find(opts, desc->name)) {
if (!options[i].assigned) {
/* only change explicitly defined options */ /* only change explicitly defined options */
desc++;
continue; continue;
} }
if (!strcmp(options[i].name, "compat")) { if (!strcmp(desc->name, "compat")) {
if (!options[i].value.s) { compat = qemu_opt_get(opts, "compat");
if (!compat) {
/* preserve default */ /* preserve default */
} else if (!strcmp(options[i].value.s, "0.10")) { } else if (!strcmp(compat, "0.10")) {
new_version = 2; new_version = 2;
} else if (!strcmp(options[i].value.s, "1.1")) { } else if (!strcmp(compat, "1.1")) {
new_version = 3; new_version = 3;
} else { } else {
fprintf(stderr, "Unknown compatibility level %s.\n", fprintf(stderr, "Unknown compatibility level %s.\n", compat);
options[i].value.s);
return -EINVAL; return -EINVAL;
} }
} else if (!strcmp(options[i].name, "preallocation")) { } else if (!strcmp(desc->name, "preallocation")) {
fprintf(stderr, "Cannot change preallocation mode.\n"); fprintf(stderr, "Cannot change preallocation mode.\n");
return -ENOTSUP; return -ENOTSUP;
} else if (!strcmp(options[i].name, "size")) { } else if (!strcmp(desc->name, "size")) {
new_size = options[i].value.n; new_size = qemu_opt_get_size(opts, "size", 0);
} else if (!strcmp(options[i].name, "backing_file")) { } else if (!strcmp(desc->name, "backing_file")) {
backing_file = options[i].value.s; backing_file = qemu_opt_get(opts, "backing_file");
} else if (!strcmp(options[i].name, "backing_fmt")) { } else if (!strcmp(desc->name, "backing_fmt")) {
backing_format = options[i].value.s; backing_format = qemu_opt_get(opts, "backing_fmt");
} else if (!strcmp(options[i].name, "encryption")) { } else if (!strcmp(desc->name, "encryption")) {
if ((options[i].value.n != !!s->crypt_method)) { encrypt = qemu_opt_get_bool(opts, "encryption", s->crypt_method);
if (encrypt != !!s->crypt_method) {
fprintf(stderr, "Changing the encryption flag is not " fprintf(stderr, "Changing the encryption flag is not "
"supported.\n"); "supported.\n");
return -ENOTSUP; return -ENOTSUP;
} }
} else if (!strcmp(options[i].name, "cluster_size")) { } else if (!strcmp(desc->name, "cluster_size")) {
if (options[i].value.n != s->cluster_size) { cluster_size = qemu_opt_get_size(opts, "cluster_size",
cluster_size);
if (cluster_size != s->cluster_size) {
fprintf(stderr, "Changing the cluster size is not " fprintf(stderr, "Changing the cluster size is not "
"supported.\n"); "supported.\n");
return -ENOTSUP; return -ENOTSUP;
} }
} else if (!strcmp(options[i].name, "lazy_refcounts")) { } else if (!strcmp(desc->name, "lazy_refcounts")) {
lazy_refcounts = options[i].value.n; lazy_refcounts = qemu_opt_get_bool(opts, "lazy_refcounts",
lazy_refcounts);
} else { } else {
/* if this assertion fails, this probably means a new option was /* if this assertion fails, this probably means a new option was
* added without having it covered here */ * added without having it covered here */
assert(false); assert(false);
} }
desc++;
} }
if (new_version != old_version) { if (new_version != old_version) {
@ -2324,49 +2335,55 @@ static int qcow2_amend_options(BlockDriverState *bs,
return 0; return 0;
} }
static QEMUOptionParameter qcow2_create_options[] = { static QemuOptsList qcow2_create_opts = {
{ .name = "qcow2-create-opts",
.name = BLOCK_OPT_SIZE, .head = QTAILQ_HEAD_INITIALIZER(qcow2_create_opts.head),
.type = OPT_SIZE, .desc = {
.help = "Virtual disk size" {
}, .name = BLOCK_OPT_SIZE,
{ .type = QEMU_OPT_SIZE,
.name = BLOCK_OPT_COMPAT_LEVEL, .help = "Virtual disk size"
.type = OPT_STRING, },
.help = "Compatibility level (0.10 or 1.1)" {
}, .name = BLOCK_OPT_COMPAT_LEVEL,
{ .type = QEMU_OPT_STRING,
.name = BLOCK_OPT_BACKING_FILE, .help = "Compatibility level (0.10 or 1.1)"
.type = OPT_STRING, },
.help = "File name of a base image" {
}, .name = BLOCK_OPT_BACKING_FILE,
{ .type = QEMU_OPT_STRING,
.name = BLOCK_OPT_BACKING_FMT, .help = "File name of a base image"
.type = OPT_STRING, },
.help = "Image format of the base image" {
}, .name = BLOCK_OPT_BACKING_FMT,
{ .type = QEMU_OPT_STRING,
.name = BLOCK_OPT_ENCRYPT, .help = "Image format of the base image"
.type = OPT_FLAG, },
.help = "Encrypt the image" {
}, .name = BLOCK_OPT_ENCRYPT,
{ .type = QEMU_OPT_BOOL,
.name = BLOCK_OPT_CLUSTER_SIZE, .help = "Encrypt the image",
.type = OPT_SIZE, .def_value_str = "off"
.help = "qcow2 cluster size", },
.value = { .n = DEFAULT_CLUSTER_SIZE }, {
}, .name = BLOCK_OPT_CLUSTER_SIZE,
{ .type = QEMU_OPT_SIZE,
.name = BLOCK_OPT_PREALLOC, .help = "qcow2 cluster size",
.type = OPT_STRING, .def_value_str = stringify(DEFAULT_CLUSTER_SIZE)
.help = "Preallocation mode (allowed values: off, metadata)" },
}, {
{ .name = BLOCK_OPT_PREALLOC,
.name = BLOCK_OPT_LAZY_REFCOUNTS, .type = QEMU_OPT_STRING,
.type = OPT_FLAG, .help = "Preallocation mode (allowed values: off, metadata)"
.help = "Postpone refcount updates", },
}, {
{ NULL } .name = BLOCK_OPT_LAZY_REFCOUNTS,
.type = QEMU_OPT_BOOL,
.help = "Postpone refcount updates",
.def_value_str = "off"
},
{ /* end of list */ }
}
}; };
static BlockDriver bdrv_qcow2 = { static BlockDriver bdrv_qcow2 = {
@ -2376,7 +2393,7 @@ static BlockDriver bdrv_qcow2 = {
.bdrv_open = qcow2_open, .bdrv_open = qcow2_open,
.bdrv_close = qcow2_close, .bdrv_close = qcow2_close,
.bdrv_reopen_prepare = qcow2_reopen_prepare, .bdrv_reopen_prepare = qcow2_reopen_prepare,
.bdrv_create = qcow2_create, .bdrv_create2 = qcow2_create,
.bdrv_has_zero_init = bdrv_has_zero_init_1, .bdrv_has_zero_init = bdrv_has_zero_init_1,
.bdrv_co_get_block_status = qcow2_co_get_block_status, .bdrv_co_get_block_status = qcow2_co_get_block_status,
.bdrv_set_key = qcow2_set_key, .bdrv_set_key = qcow2_set_key,
@ -2394,8 +2411,8 @@ static BlockDriver bdrv_qcow2 = {
.bdrv_snapshot_goto = qcow2_snapshot_goto, .bdrv_snapshot_goto = qcow2_snapshot_goto,
.bdrv_snapshot_delete = qcow2_snapshot_delete, .bdrv_snapshot_delete = qcow2_snapshot_delete,
.bdrv_snapshot_list = qcow2_snapshot_list, .bdrv_snapshot_list = qcow2_snapshot_list,
.bdrv_snapshot_load_tmp = qcow2_snapshot_load_tmp, .bdrv_snapshot_load_tmp = qcow2_snapshot_load_tmp,
.bdrv_get_info = qcow2_get_info, .bdrv_get_info = qcow2_get_info,
.bdrv_get_specific_info = qcow2_get_specific_info, .bdrv_get_specific_info = qcow2_get_specific_info,
.bdrv_save_vmstate = qcow2_save_vmstate, .bdrv_save_vmstate = qcow2_save_vmstate,
@ -2406,9 +2423,9 @@ static BlockDriver bdrv_qcow2 = {
.bdrv_refresh_limits = qcow2_refresh_limits, .bdrv_refresh_limits = qcow2_refresh_limits,
.bdrv_invalidate_cache = qcow2_invalidate_cache, .bdrv_invalidate_cache = qcow2_invalidate_cache,
.create_options = qcow2_create_options, .create_opts = &qcow2_create_opts,
.bdrv_check = qcow2_check, .bdrv_check = qcow2_check,
.bdrv_amend_options = qcow2_amend_options, .bdrv_amend_options2 = qcow2_amend_options,
}; };
static void bdrv_qcow2_init(void) static void bdrv_qcow2_init(void)