Change block layer to support both QemuOpts and QEMUOptionParameter.
After this patch, it will change backend drivers one by one. At the end,
QEMUOptionParameter will be removed and only QemuOpts is kept.
Signed-off-by: Dong Xu Wang <wdongxu@linux.vnet.ibm.com>
Signed-off-by: Chunyan Liu <cyliu@suse.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
}
}
+ if (bdrv->bdrv_create) {
+ assert(!bdrv->bdrv_create2 && !bdrv->create_opts);
+ assert(!bdrv->bdrv_amend_options2);
+ } else if (bdrv->bdrv_create2) {
+ assert(!bdrv->bdrv_create && !bdrv->create_options);
+ assert(!bdrv->bdrv_amend_options);
+ }
QLIST_INSERT_HEAD(&bdrv_drivers, bdrv, list);
}
BlockDriver *drv;
char *filename;
QEMUOptionParameter *options;
+ QemuOpts *opts;
int ret;
Error *err;
} CreateCo;
CreateCo *cco = opaque;
assert(cco->drv);
+ assert(!(cco->options && cco->opts));
- ret = cco->drv->bdrv_create(cco->filename, cco->options, &local_err);
+ if (cco->drv->bdrv_create2) {
+ QemuOptsList *opts_list = NULL;
+ if (cco->options) {
+ opts_list = params_to_opts(cco->options);
+ cco->opts = qemu_opts_create(opts_list, NULL, 0, &error_abort);
+ }
+ ret = cco->drv->bdrv_create2(cco->filename, cco->opts, &local_err);
+ if (cco->options) {
+ qemu_opts_del(cco->opts);
+ qemu_opts_free(opts_list);
+ }
+ } else {
+ if (cco->opts) {
+ cco->options = opts_to_params(cco->opts);
+ }
+ ret = cco->drv->bdrv_create(cco->filename, cco->options, &local_err);
+ if (cco->opts) {
+ free_option_parameters(cco->options);
+ }
+ }
if (local_err) {
error_propagate(&cco->err, local_err);
}
}
int bdrv_create(BlockDriver *drv, const char* filename,
- QEMUOptionParameter *options, Error **errp)
+ QEMUOptionParameter *options,
+ QemuOpts *opts, Error **errp)
{
int ret;
.drv = drv,
.filename = g_strdup(filename),
.options = options,
+ .opts = opts,
.ret = NOT_DONE,
.err = NULL,
};
- if (!drv->bdrv_create) {
+ if (!drv->bdrv_create && !drv->bdrv_create2) {
error_setg(errp, "Driver '%s' does not support image creation", drv->format_name);
ret = -ENOTSUP;
goto out;
}
int bdrv_create_file(const char* filename, QEMUOptionParameter *options,
- Error **errp)
+ QemuOpts *opts, Error **errp)
{
BlockDriver *drv;
Error *local_err = NULL;
return -ENOENT;
}
- ret = bdrv_create(drv, filename, options, &local_err);
+ ret = bdrv_create(drv, filename, options, opts, &local_err);
if (local_err) {
error_propagate(errp, local_err);
}
char *tmp_filename = g_malloc0(PATH_MAX + 1);
int64_t total_size;
BlockDriver *bdrv_qcow2;
- QEMUOptionParameter *create_options;
+ QemuOptsList *create_opts = NULL;
+ QemuOpts *opts = NULL;
QDict *snapshot_options;
BlockDriverState *bs_snapshot;
Error *local_err;
}
bdrv_qcow2 = bdrv_find_format("qcow2");
- create_options = parse_option_parameters("", bdrv_qcow2->create_options,
- NULL);
-
- set_option_parameter_int(create_options, BLOCK_OPT_SIZE, total_size);
- ret = bdrv_create(bdrv_qcow2, tmp_filename, create_options, &local_err);
- free_option_parameters(create_options);
+ assert(!(bdrv_qcow2->create_options && bdrv_qcow2->create_opts));
+ if (bdrv_qcow2->create_options) {
+ create_opts = params_to_opts(bdrv_qcow2->create_options);
+ } else {
+ create_opts = bdrv_qcow2->create_opts;
+ }
+ opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
+ qemu_opt_set_number(opts, BLOCK_OPT_SIZE, total_size);
+ ret = bdrv_create(bdrv_qcow2, tmp_filename, NULL, opts, &local_err);
+ qemu_opts_del(opts);
+ if (bdrv_qcow2->create_options) {
+ qemu_opts_free(create_opts);
+ }
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not create temporary overlay "
"'%s': %s", tmp_filename,
char *options, uint64_t img_size, int flags,
Error **errp, bool quiet)
{
- QEMUOptionParameter *param = NULL, *create_options = NULL;
- QEMUOptionParameter *backing_fmt, *backing_file, *size;
+ QemuOptsList *create_opts = NULL;
+ QemuOpts *opts = NULL;
+ const char *backing_fmt, *backing_file;
+ int64_t size;
BlockDriver *drv, *proto_drv;
BlockDriver *backing_drv = NULL;
Error *local_err = NULL;
return;
}
- create_options = append_option_parameters(create_options,
- drv->create_options);
- create_options = append_option_parameters(create_options,
- proto_drv->create_options);
+ create_opts = qemu_opts_append(create_opts, drv->create_opts,
+ drv->create_options);
+ create_opts = qemu_opts_append(create_opts, proto_drv->create_opts,
+ proto_drv->create_options);
/* Create parameter list with default values */
- param = parse_option_parameters("", create_options, param);
-
- set_option_parameter_int(param, BLOCK_OPT_SIZE, img_size);
+ opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
+ qemu_opt_set_number(opts, BLOCK_OPT_SIZE, img_size);
/* Parse -o options */
if (options) {
- param = parse_option_parameters(options, create_options, param);
- if (param == NULL) {
- error_setg(errp, "Invalid options for file format '%s'.", fmt);
+ if (qemu_opts_do_parse(opts, options, NULL) != 0) {
+ error_setg(errp, "Invalid options for file format '%s'", fmt);
goto out;
}
}
if (base_filename) {
- if (set_option_parameter(param, BLOCK_OPT_BACKING_FILE,
- base_filename)) {
+ if (qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, base_filename)) {
error_setg(errp, "Backing file not supported for file format '%s'",
fmt);
goto out;
}
if (base_fmt) {
- if (set_option_parameter(param, BLOCK_OPT_BACKING_FMT, base_fmt)) {
+ if (qemu_opt_set(opts, BLOCK_OPT_BACKING_FMT, base_fmt)) {
error_setg(errp, "Backing file format not supported for file "
"format '%s'", fmt);
goto out;
}
}
- backing_file = get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
- if (backing_file && backing_file->value.s) {
- if (!strcmp(filename, backing_file->value.s)) {
+ backing_file = qemu_opt_get(opts, BLOCK_OPT_BACKING_FILE);
+ if (backing_file) {
+ if (!strcmp(filename, backing_file)) {
error_setg(errp, "Error: Trying to create an image with the "
"same filename as the backing file");
goto out;
}
}
- backing_fmt = get_option_parameter(param, BLOCK_OPT_BACKING_FMT);
- if (backing_fmt && backing_fmt->value.s) {
- backing_drv = bdrv_find_format(backing_fmt->value.s);
+ backing_fmt = qemu_opt_get(opts, BLOCK_OPT_BACKING_FMT);
+ if (backing_fmt) {
+ backing_drv = bdrv_find_format(backing_fmt);
if (!backing_drv) {
error_setg(errp, "Unknown backing file format '%s'",
- backing_fmt->value.s);
+ backing_fmt);
goto out;
}
}
// The size for the image must always be specified, with one exception:
// If we are using a backing file, we can obtain the size from there
- size = get_option_parameter(param, BLOCK_OPT_SIZE);
- if (size && size->value.n == -1) {
- if (backing_file && backing_file->value.s) {
+ size = qemu_opt_get_size(opts, BLOCK_OPT_SIZE, 0);
+ if (size == -1) {
+ if (backing_file) {
BlockDriverState *bs;
uint64_t size;
char buf[32];
flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
bs = NULL;
- ret = bdrv_open(&bs, backing_file->value.s, NULL, NULL, back_flags,
+ ret = bdrv_open(&bs, backing_file, NULL, NULL, back_flags,
backing_drv, &local_err);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not open '%s': %s",
- backing_file->value.s,
+ backing_file,
error_get_pretty(local_err));
error_free(local_err);
local_err = NULL;
size *= 512;
snprintf(buf, sizeof(buf), "%" PRId64, size);
- set_option_parameter(param, BLOCK_OPT_SIZE, buf);
+ qemu_opt_set_number(opts, BLOCK_OPT_SIZE, size);
bdrv_unref(bs);
} else {
if (!quiet) {
printf("Formatting '%s', fmt=%s ", filename, fmt);
- print_option_parameters(param);
+ qemu_opts_print(opts);
puts("");
}
- ret = bdrv_create(drv, filename, param, &local_err);
+
+ ret = bdrv_create(drv, filename, NULL, opts, &local_err);
+
if (ret == -EFBIG) {
/* This is generally a better message than whatever the driver would
* deliver (especially because of the cluster_size_hint), since that
* is most probably not much different from "image too large". */
const char *cluster_size_hint = "";
- if (get_option_parameter(create_options, BLOCK_OPT_CLUSTER_SIZE)) {
+ if (qemu_opt_get_size(opts, BLOCK_OPT_CLUSTER_SIZE, 0)) {
cluster_size_hint = " (try using a larger cluster size)";
}
error_setg(errp, "The image size is too large for file format '%s'"
}
out:
- free_option_parameters(create_options);
- free_option_parameters(param);
-
+ qemu_opts_del(opts);
+ qemu_opts_free(create_opts);
if (local_err) {
error_propagate(errp, local_err);
}
notifier_with_return_list_add(&bs->before_write_notifiers, notifier);
}
-int bdrv_amend_options(BlockDriverState *bs, QEMUOptionParameter *options)
+int bdrv_amend_options(BlockDriverState *bs, QEMUOptionParameter *options,
+ QemuOpts *opts)
{
- if (bs->drv->bdrv_amend_options == NULL) {
+ int ret;
+ assert(!(options && opts));
+
+ if (!bs->drv->bdrv_amend_options && !bs->drv->bdrv_amend_options2) {
return -ENOTSUP;
}
- return bs->drv->bdrv_amend_options(bs, options);
+ if (bs->drv->bdrv_amend_options2) {
+ QemuOptsList *opts_list = NULL;
+ if (options) {
+ opts_list = params_to_opts(options);
+ opts = qemu_opts_create(opts_list, NULL, 0, &error_abort);
+ }
+ ret = bs->drv->bdrv_amend_options2(bs, opts);
+ if (options) {
+ qemu_opts_del(opts);
+ qemu_opts_free(opts_list);
+ }
+ } else {
+ if (opts) {
+ options = opts_to_params(opts);
+ }
+ ret = bs->drv->bdrv_amend_options(bs, options);
+ if (opts) {
+ free_option_parameters(options);
+ }
+ }
+ return ret;
}
/* This function will be called by the bdrv_recurse_is_first_non_filter method
options++;
}
- ret = bdrv_create_file(filename, options, &local_err);
+ ret = bdrv_create_file(filename, options, NULL, &local_err);
if (ret < 0) {
error_propagate(errp, local_err);
return ret;
options++;
}
- ret = bdrv_create_file(filename, options, &local_err);
+ ret = bdrv_create_file(filename, options, NULL, &local_err);
if (ret < 0) {
error_propagate(errp, local_err);
return ret;
Error *local_err = NULL;
int ret;
- ret = bdrv_create_file(filename, options, &local_err);
+ ret = bdrv_create_file(filename, options, NULL, &local_err);
if (ret < 0) {
error_propagate(errp, local_err);
return ret;
int ret = 0;
BlockDriverState *bs;
- ret = bdrv_create_file(filename, NULL, &local_err);
+ ret = bdrv_create_file(filename, NULL, NULL, &local_err);
if (ret < 0) {
error_propagate(errp, local_err);
return ret;
Error *local_err = NULL;
int ret;
- ret = bdrv_create_file(filename, options, &local_err);
+ ret = bdrv_create_file(filename, options, NULL, &local_err);
if (local_err) {
error_propagate(errp, local_err);
}
block_size = block_size > VHDX_BLOCK_SIZE_MAX ? VHDX_BLOCK_SIZE_MAX :
block_size;
- ret = bdrv_create_file(filename, options, &local_err);
+ ret = bdrv_create_file(filename, options, NULL, &local_err);
if (ret < 0) {
error_propagate(errp, local_err);
goto exit;
uint32_t *gd_buf = NULL;
int gd_buf_size;
- ret = bdrv_create_file(filename, NULL, &local_err);
+ ret = bdrv_create_file(filename, NULL, NULL, &local_err);
if (ret < 0) {
error_propagate(errp, local_err);
goto exit;
if (!split && !flat) {
desc_offset = 0x200;
} else {
- ret = bdrv_create_file(filename, options, &local_err);
+ ret = bdrv_create_file(filename, options, NULL, &local_err);
if (ret < 0) {
error_propagate(errp, local_err);
goto exit;
set_option_parameter_int(options, BLOCK_OPT_SIZE, s->sector_count * 512);
set_option_parameter(options, BLOCK_OPT_BACKING_FILE, "fat:");
- ret = bdrv_create(bdrv_qcow, s->qcow_filename, options, errp);
+ ret = bdrv_create(bdrv_qcow, s->qcow_filename, options, NULL, errp);
free_option_parameters(options);
if (ret < 0) {
goto err;
BlockDriver *bdrv_find_whitelisted_format(const char *format_name,
bool readonly);
int bdrv_create(BlockDriver *drv, const char* filename,
- QEMUOptionParameter *options, Error **errp);
+ QEMUOptionParameter *options, QemuOpts *opts, Error **errp);
int bdrv_create_file(const char* filename, QEMUOptionParameter *options,
- Error **errp);
+ QemuOpts *opts, Error **errp);
BlockDriverState *bdrv_new(const char *device_name, Error **errp);
void bdrv_make_anon(BlockDriverState *bs);
void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old);
int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix);
-int bdrv_amend_options(BlockDriverState *bs_new, QEMUOptionParameter *options);
+int bdrv_amend_options(BlockDriverState *bs_new, QEMUOptionParameter *options,
+ QemuOpts *opts);
/* external snapshots */
bool bdrv_recurse_is_first_non_filter(BlockDriverState *bs,
void (*bdrv_rebind)(BlockDriverState *bs);
int (*bdrv_create)(const char *filename, QEMUOptionParameter *options,
Error **errp);
+ /* FIXME: will remove the duplicate and rename back to bdrv_create later */
+ int (*bdrv_create2)(const char *filename, QemuOpts *opts, Error **errp);
int (*bdrv_set_key)(BlockDriverState *bs, const char *key);
int (*bdrv_make_empty)(BlockDriverState *bs);
/* aio */
/* List of options for creating images, terminated by name == NULL */
QEMUOptionParameter *create_options;
-
+ /* FIXME: will replace create_options.
+ * These two fields are mutually exclusive. At most one is non-NULL.
+ * create_options should only be set with bdrv_create, and create_opts
+ * should only be set with bdrv_create2.
+ */
+ QemuOptsList *create_opts;
/*
* Returns 0 for completed check, -errno for internal errors.
int (*bdrv_amend_options)(BlockDriverState *bs,
QEMUOptionParameter *options);
+ /* FIXME: will remove the duplicate and rename back to
+ * bdrv_amend_options later
+ */
+ int (*bdrv_amend_options2)(BlockDriverState *bs, QemuOpts *opts);
void (*bdrv_debug_event)(BlockDriverState *bs, BlkDebugEvent event);
static int print_block_option_help(const char *filename, const char *fmt)
{
BlockDriver *drv, *proto_drv;
- QEMUOptionParameter *create_options = NULL;
+ QemuOptsList *create_opts = NULL;
/* Find driver and parse its options */
drv = bdrv_find_format(fmt);
return 1;
}
- create_options = append_option_parameters(create_options,
- drv->create_options);
-
+ create_opts = qemu_opts_append(create_opts, drv->create_opts,
+ drv->create_options);
if (filename) {
proto_drv = bdrv_find_protocol(filename, true);
if (!proto_drv) {
error_report("Unknown protocol '%s'", filename);
- free_option_parameters(create_options);
+ qemu_opts_free(create_opts);
return 1;
}
- create_options = append_option_parameters(create_options,
- proto_drv->create_options);
+ create_opts = qemu_opts_append(create_opts, proto_drv->create_opts,
+ proto_drv->create_options);
}
- print_option_help(create_options);
- free_option_parameters(create_options);
+ qemu_opts_print_help(create_opts);
+ qemu_opts_free(create_opts);
return 0;
}
return NULL;
}
-static int add_old_style_options(const char *fmt, QEMUOptionParameter *list,
+static int add_old_style_options(const char *fmt, QemuOpts *opts,
const char *base_filename,
const char *base_fmt)
{
if (base_filename) {
- if (set_option_parameter(list, BLOCK_OPT_BACKING_FILE, base_filename)) {
+ if (qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, base_filename)) {
error_report("Backing file not supported for file format '%s'",
fmt);
return -1;
}
}
if (base_fmt) {
- if (set_option_parameter(list, BLOCK_OPT_BACKING_FMT, base_fmt)) {
+ if (qemu_opt_set(opts, BLOCK_OPT_BACKING_FMT, base_fmt)) {
error_report("Backing file format not supported for file "
"format '%s'", fmt);
return -1;
size_t bufsectors = IO_BUF_SIZE / BDRV_SECTOR_SIZE;
const uint8_t *buf1;
BlockDriverInfo bdi;
- QEMUOptionParameter *param = NULL, *create_options = NULL;
- QEMUOptionParameter *out_baseimg_param;
+ QemuOpts *opts = NULL;
+ QemuOptsList *create_opts = NULL;
+ const char *out_baseimg_param;
char *options = NULL;
const char *snapshot_name = NULL;
int min_sparse = 8; /* Need at least 4k of zeros for sparse detection */
goto out;
}
- create_options = append_option_parameters(create_options,
- drv->create_options);
- create_options = append_option_parameters(create_options,
- proto_drv->create_options);
+ create_opts = qemu_opts_append(create_opts, drv->create_opts,
+ drv->create_options);
+ create_opts = qemu_opts_append(create_opts, proto_drv->create_opts,
+ proto_drv->create_options);
- if (options) {
- param = parse_option_parameters(options, create_options, param);
- if (param == NULL) {
- error_report("Invalid options for file format '%s'.", out_fmt);
- ret = -1;
- goto out;
- }
- } else {
- param = parse_option_parameters("", create_options, param);
+ opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
+ if (options && qemu_opts_do_parse(opts, options, NULL)) {
+ error_report("Invalid options for file format '%s'", out_fmt);
+ ret = -1;
+ goto out;
}
- set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512);
- ret = add_old_style_options(out_fmt, param, out_baseimg, NULL);
+ qemu_opt_set_number(opts, BLOCK_OPT_SIZE, total_sectors * 512);
+ ret = add_old_style_options(out_fmt, opts, out_baseimg, NULL);
if (ret < 0) {
goto out;
}
/* Get backing file name if -o backing_file was used */
- out_baseimg_param = get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
+ out_baseimg_param = qemu_opt_get(opts, BLOCK_OPT_BACKING_FILE);
if (out_baseimg_param) {
- out_baseimg = out_baseimg_param->value.s;
+ out_baseimg = out_baseimg_param;
}
/* Check if compression is supported */
if (compress) {
- QEMUOptionParameter *encryption =
- get_option_parameter(param, BLOCK_OPT_ENCRYPT);
- QEMUOptionParameter *preallocation =
- get_option_parameter(param, BLOCK_OPT_PREALLOC);
+ bool encryption =
+ qemu_opt_get_bool(opts, BLOCK_OPT_ENCRYPT, false);
+ const char *preallocation =
+ qemu_opt_get(opts, BLOCK_OPT_PREALLOC);
if (!drv->bdrv_write_compressed) {
error_report("Compression not supported for this file format");
goto out;
}
- if (encryption && encryption->value.n) {
+ if (encryption) {
error_report("Compression and encryption not supported at "
"the same time");
ret = -1;
goto out;
}
- if (preallocation && preallocation->value.s
- && strcmp(preallocation->value.s, "off"))
+ if (preallocation
+ && strcmp(preallocation, "off"))
{
error_report("Compression and preallocation not supported at "
"the same time");
if (!skip_create) {
/* Create the new image */
- ret = bdrv_create(drv, out_filename, param, &local_err);
+ ret = bdrv_create(drv, out_filename, NULL, opts, &local_err);
if (ret < 0) {
error_report("%s: error while converting %s: %s",
out_filename, out_fmt, error_get_pretty(local_err));
qemu_progress_print(100, 0);
}
qemu_progress_end();
- free_option_parameters(create_options);
- free_option_parameters(param);
+ qemu_opts_del(opts);
+ qemu_opts_free(create_opts);
qemu_vfree(buf);
if (sn_opts) {
qemu_opts_del(sn_opts);
{
int c, ret = 0;
char *options = NULL;
- QEMUOptionParameter *create_options = NULL, *options_param = NULL;
+ QemuOptsList *create_opts = NULL;
+ QemuOpts *opts = NULL;
const char *fmt = NULL, *filename;
bool quiet = false;
BlockDriverState *bs = NULL;
goto out;
}
- create_options = append_option_parameters(create_options,
- bs->drv->create_options);
- options_param = parse_option_parameters(options, create_options,
- options_param);
- if (options_param == NULL) {
+ create_opts = qemu_opts_append(create_opts, bs->drv->create_opts,
+ bs->drv->create_options);
+ opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
+ if (options && qemu_opts_do_parse(opts, options, NULL)) {
error_report("Invalid options for file format '%s'", fmt);
ret = -1;
goto out;
}
- ret = bdrv_amend_options(bs, options_param);
+ ret = bdrv_amend_options(bs, NULL, opts);
if (ret < 0) {
error_report("Error while amending options: %s", strerror(-ret));
goto out;
if (bs) {
bdrv_unref(bs);
}
- free_option_parameters(create_options);
- free_option_parameters(options_param);
+ qemu_opts_del(opts);
+ qemu_opts_free(create_opts);
g_free(options);
if (ret) {
qemu-img create -f qcow2 -o size=foobar TEST_DIR/t.qcow2
qemu-img: Parameter 'size' expects a size
-qemu-img: TEST_DIR/t.qcow2: Invalid options for file format 'qcow2'.
+qemu-img: TEST_DIR/t.qcow2: Invalid options for file format 'qcow2'
== Check correct interpretation of suffixes for cluster size ==
qemu-img: Error while amending options: Invalid argument
Unknown compatibility level 0.42.
qemu-img: Error while amending options: Invalid argument
-Unknown option 'foo'
+qemu-img: Invalid parameter 'foo'
qemu-img: Invalid options for file format 'qcow2'
Changing the cluster size is not supported.
qemu-img: Error while amending options: Operation not supported