change block layer to support both QemuOpts and QEMUOptionParamter

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>
This commit is contained in:
Chunyan Liu 2014-06-05 17:20:51 +08:00 committed by Stefan Hajnoczi
parent 4782183da3
commit 83d0521a1e
14 changed files with 184 additions and 114 deletions

160
block.c
View File

@ -329,6 +329,13 @@ void bdrv_register(BlockDriver *bdrv)
} }
} }
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); QLIST_INSERT_HEAD(&bdrv_drivers, bdrv, list);
} }
@ -425,6 +432,7 @@ typedef struct CreateCo {
BlockDriver *drv; BlockDriver *drv;
char *filename; char *filename;
QEMUOptionParameter *options; QEMUOptionParameter *options;
QemuOpts *opts;
int ret; int ret;
Error *err; Error *err;
} CreateCo; } CreateCo;
@ -436,8 +444,28 @@ static void coroutine_fn bdrv_create_co_entry(void *opaque)
CreateCo *cco = opaque; CreateCo *cco = opaque;
assert(cco->drv); 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) { if (local_err) {
error_propagate(&cco->err, local_err); error_propagate(&cco->err, local_err);
} }
@ -445,7 +473,8 @@ static void coroutine_fn bdrv_create_co_entry(void *opaque)
} }
int bdrv_create(BlockDriver *drv, const char* filename, int bdrv_create(BlockDriver *drv, const char* filename,
QEMUOptionParameter *options, Error **errp) QEMUOptionParameter *options,
QemuOpts *opts, Error **errp)
{ {
int ret; int ret;
@ -454,11 +483,12 @@ int bdrv_create(BlockDriver *drv, const char* filename,
.drv = drv, .drv = drv,
.filename = g_strdup(filename), .filename = g_strdup(filename),
.options = options, .options = options,
.opts = opts,
.ret = NOT_DONE, .ret = NOT_DONE,
.err = NULL, .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); error_setg(errp, "Driver '%s' does not support image creation", drv->format_name);
ret = -ENOTSUP; ret = -ENOTSUP;
goto out; goto out;
@ -490,7 +520,7 @@ out:
} }
int bdrv_create_file(const char* filename, QEMUOptionParameter *options, int bdrv_create_file(const char* filename, QEMUOptionParameter *options,
Error **errp) QemuOpts *opts, Error **errp)
{ {
BlockDriver *drv; BlockDriver *drv;
Error *local_err = NULL; Error *local_err = NULL;
@ -502,7 +532,7 @@ int bdrv_create_file(const char* filename, QEMUOptionParameter *options,
return -ENOENT; return -ENOENT;
} }
ret = bdrv_create(drv, filename, options, &local_err); ret = bdrv_create(drv, filename, options, opts, &local_err);
if (local_err) { if (local_err) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
} }
@ -1247,7 +1277,8 @@ void bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp)
char *tmp_filename = g_malloc0(PATH_MAX + 1); char *tmp_filename = g_malloc0(PATH_MAX + 1);
int64_t total_size; int64_t total_size;
BlockDriver *bdrv_qcow2; BlockDriver *bdrv_qcow2;
QEMUOptionParameter *create_options; QemuOptsList *create_opts = NULL;
QemuOpts *opts = NULL;
QDict *snapshot_options; QDict *snapshot_options;
BlockDriverState *bs_snapshot; BlockDriverState *bs_snapshot;
Error *local_err; Error *local_err;
@ -1272,13 +1303,20 @@ void bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp)
} }
bdrv_qcow2 = bdrv_find_format("qcow2"); 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); assert(!(bdrv_qcow2->create_options && bdrv_qcow2->create_opts));
if (bdrv_qcow2->create_options) {
ret = bdrv_create(bdrv_qcow2, tmp_filename, create_options, &local_err); create_opts = params_to_opts(bdrv_qcow2->create_options);
free_option_parameters(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) { if (ret < 0) {
error_setg_errno(errp, -ret, "Could not create temporary overlay " error_setg_errno(errp, -ret, "Could not create temporary overlay "
"'%s': %s", tmp_filename, "'%s': %s", tmp_filename,
@ -5519,8 +5557,10 @@ void bdrv_img_create(const char *filename, const char *fmt,
char *options, uint64_t img_size, int flags, char *options, uint64_t img_size, int flags,
Error **errp, bool quiet) Error **errp, bool quiet)
{ {
QEMUOptionParameter *param = NULL, *create_options = NULL; QemuOptsList *create_opts = NULL;
QEMUOptionParameter *backing_fmt, *backing_file, *size; QemuOpts *opts = NULL;
const char *backing_fmt, *backing_file;
int64_t size;
BlockDriver *drv, *proto_drv; BlockDriver *drv, *proto_drv;
BlockDriver *backing_drv = NULL; BlockDriver *backing_drv = NULL;
Error *local_err = NULL; Error *local_err = NULL;
@ -5539,28 +5579,25 @@ void bdrv_img_create(const char *filename, const char *fmt,
return; return;
} }
create_options = append_option_parameters(create_options, create_opts = qemu_opts_append(create_opts, drv->create_opts,
drv->create_options); drv->create_options);
create_options = append_option_parameters(create_options, create_opts = qemu_opts_append(create_opts, proto_drv->create_opts,
proto_drv->create_options); proto_drv->create_options);
/* Create parameter list with default values */ /* Create parameter list with default values */
param = parse_option_parameters("", create_options, param); opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
qemu_opt_set_number(opts, BLOCK_OPT_SIZE, img_size);
set_option_parameter_int(param, BLOCK_OPT_SIZE, img_size);
/* Parse -o options */ /* Parse -o options */
if (options) { if (options) {
param = parse_option_parameters(options, create_options, param); if (qemu_opts_do_parse(opts, options, NULL) != 0) {
if (param == NULL) { error_setg(errp, "Invalid options for file format '%s'", fmt);
error_setg(errp, "Invalid options for file format '%s'.", fmt);
goto out; goto out;
} }
} }
if (base_filename) { if (base_filename) {
if (set_option_parameter(param, BLOCK_OPT_BACKING_FILE, if (qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, base_filename)) {
base_filename)) {
error_setg(errp, "Backing file not supported for file format '%s'", error_setg(errp, "Backing file not supported for file format '%s'",
fmt); fmt);
goto out; goto out;
@ -5568,37 +5605,37 @@ void bdrv_img_create(const char *filename, const char *fmt,
} }
if (base_fmt) { 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 " error_setg(errp, "Backing file format not supported for file "
"format '%s'", fmt); "format '%s'", fmt);
goto out; goto out;
} }
} }
backing_file = get_option_parameter(param, BLOCK_OPT_BACKING_FILE); backing_file = qemu_opt_get(opts, BLOCK_OPT_BACKING_FILE);
if (backing_file && backing_file->value.s) { if (backing_file) {
if (!strcmp(filename, backing_file->value.s)) { if (!strcmp(filename, backing_file)) {
error_setg(errp, "Error: Trying to create an image with the " error_setg(errp, "Error: Trying to create an image with the "
"same filename as the backing file"); "same filename as the backing file");
goto out; goto out;
} }
} }
backing_fmt = get_option_parameter(param, BLOCK_OPT_BACKING_FMT); backing_fmt = qemu_opt_get(opts, BLOCK_OPT_BACKING_FMT);
if (backing_fmt && backing_fmt->value.s) { if (backing_fmt) {
backing_drv = bdrv_find_format(backing_fmt->value.s); backing_drv = bdrv_find_format(backing_fmt);
if (!backing_drv) { if (!backing_drv) {
error_setg(errp, "Unknown backing file format '%s'", error_setg(errp, "Unknown backing file format '%s'",
backing_fmt->value.s); backing_fmt);
goto out; goto out;
} }
} }
// The size for the image must always be specified, with one exception: // 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 // If we are using a backing file, we can obtain the size from there
size = get_option_parameter(param, BLOCK_OPT_SIZE); size = qemu_opt_get_size(opts, BLOCK_OPT_SIZE, 0);
if (size && size->value.n == -1) { if (size == -1) {
if (backing_file && backing_file->value.s) { if (backing_file) {
BlockDriverState *bs; BlockDriverState *bs;
uint64_t size; uint64_t size;
char buf[32]; char buf[32];
@ -5609,11 +5646,11 @@ void bdrv_img_create(const char *filename, const char *fmt,
flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING); flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
bs = NULL; 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); backing_drv, &local_err);
if (ret < 0) { if (ret < 0) {
error_setg_errno(errp, -ret, "Could not open '%s': %s", error_setg_errno(errp, -ret, "Could not open '%s': %s",
backing_file->value.s, backing_file,
error_get_pretty(local_err)); error_get_pretty(local_err));
error_free(local_err); error_free(local_err);
local_err = NULL; local_err = NULL;
@ -5623,7 +5660,7 @@ void bdrv_img_create(const char *filename, const char *fmt,
size *= 512; size *= 512;
snprintf(buf, sizeof(buf), "%" PRId64, size); 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); bdrv_unref(bs);
} else { } else {
@ -5634,16 +5671,18 @@ void bdrv_img_create(const char *filename, const char *fmt,
if (!quiet) { if (!quiet) {
printf("Formatting '%s', fmt=%s ", filename, fmt); printf("Formatting '%s', fmt=%s ", filename, fmt);
print_option_parameters(param); qemu_opts_print(opts);
puts(""); puts("");
} }
ret = bdrv_create(drv, filename, param, &local_err);
ret = bdrv_create(drv, filename, NULL, opts, &local_err);
if (ret == -EFBIG) { if (ret == -EFBIG) {
/* This is generally a better message than whatever the driver would /* This is generally a better message than whatever the driver would
* deliver (especially because of the cluster_size_hint), since that * deliver (especially because of the cluster_size_hint), since that
* is most probably not much different from "image too large". */ * is most probably not much different from "image too large". */
const char *cluster_size_hint = ""; 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)"; cluster_size_hint = " (try using a larger cluster size)";
} }
error_setg(errp, "The image size is too large for file format '%s'" error_setg(errp, "The image size is too large for file format '%s'"
@ -5653,9 +5692,8 @@ void bdrv_img_create(const char *filename, const char *fmt,
} }
out: out:
free_option_parameters(create_options); qemu_opts_del(opts);
free_option_parameters(param); qemu_opts_free(create_opts);
if (local_err) { if (local_err) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
} }
@ -5731,12 +5769,36 @@ void bdrv_add_before_write_notifier(BlockDriverState *bs,
notifier_with_return_list_add(&bs->before_write_notifiers, notifier); 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 -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 /* This function will be called by the bdrv_recurse_is_first_non_filter method

View File

@ -345,7 +345,7 @@ static int cow_create(const char *filename, QEMUOptionParameter *options,
options++; options++;
} }
ret = bdrv_create_file(filename, options, &local_err); ret = bdrv_create_file(filename, options, NULL, &local_err);
if (ret < 0) { if (ret < 0) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
return ret; return ret;

View File

@ -718,7 +718,7 @@ static int qcow_create(const char *filename, QEMUOptionParameter *options,
options++; options++;
} }
ret = bdrv_create_file(filename, options, &local_err); ret = bdrv_create_file(filename, options, NULL, &local_err);
if (ret < 0) { if (ret < 0) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
return ret; return ret;

View File

@ -1626,7 +1626,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, &local_err); ret = bdrv_create_file(filename, options, NULL, &local_err);
if (ret < 0) { if (ret < 0) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
return ret; return ret;

View File

@ -586,7 +586,7 @@ static int qed_create(const char *filename, uint32_t cluster_size,
int ret = 0; int ret = 0;
BlockDriverState *bs; BlockDriverState *bs;
ret = bdrv_create_file(filename, NULL, &local_err); ret = bdrv_create_file(filename, NULL, NULL, &local_err);
if (ret < 0) { if (ret < 0) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
return ret; return ret;

View File

@ -145,7 +145,7 @@ static int raw_create(const char *filename, QEMUOptionParameter *options,
Error *local_err = NULL; Error *local_err = NULL;
int ret; int ret;
ret = bdrv_create_file(filename, options, &local_err); ret = bdrv_create_file(filename, options, NULL, &local_err);
if (local_err) { if (local_err) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
} }

View File

@ -1803,7 +1803,7 @@ static int vhdx_create(const char *filename, QEMUOptionParameter *options,
block_size = block_size > VHDX_BLOCK_SIZE_MAX ? VHDX_BLOCK_SIZE_MAX : block_size = block_size > VHDX_BLOCK_SIZE_MAX ? VHDX_BLOCK_SIZE_MAX :
block_size; block_size;
ret = bdrv_create_file(filename, options, &local_err); ret = bdrv_create_file(filename, options, NULL, &local_err);
if (ret < 0) { if (ret < 0) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
goto exit; goto exit;

View File

@ -1539,7 +1539,7 @@ static int vmdk_create_extent(const char *filename, int64_t filesize,
uint32_t *gd_buf = NULL; uint32_t *gd_buf = NULL;
int gd_buf_size; int gd_buf_size;
ret = bdrv_create_file(filename, NULL, &local_err); ret = bdrv_create_file(filename, NULL, NULL, &local_err);
if (ret < 0) { if (ret < 0) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
goto exit; goto exit;
@ -1879,7 +1879,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
if (!split && !flat) { if (!split && !flat) {
desc_offset = 0x200; desc_offset = 0x200;
} else { } else {
ret = bdrv_create_file(filename, options, &local_err); ret = bdrv_create_file(filename, options, NULL, &local_err);
if (ret < 0) { if (ret < 0) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
goto exit; goto exit;

View File

@ -2930,7 +2930,7 @@ static int enable_write_target(BDRVVVFATState *s, Error **errp)
set_option_parameter_int(options, BLOCK_OPT_SIZE, s->sector_count * 512); set_option_parameter_int(options, BLOCK_OPT_SIZE, s->sector_count * 512);
set_option_parameter(options, BLOCK_OPT_BACKING_FILE, "fat:"); 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); free_option_parameters(options);
if (ret < 0) { if (ret < 0) {
goto err; goto err;

View File

@ -204,9 +204,9 @@ BlockDriver *bdrv_find_format(const char *format_name);
BlockDriver *bdrv_find_whitelisted_format(const char *format_name, BlockDriver *bdrv_find_whitelisted_format(const char *format_name,
bool readonly); bool readonly);
int bdrv_create(BlockDriver *drv, const char* filename, 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, int bdrv_create_file(const char* filename, QEMUOptionParameter *options,
Error **errp); QemuOpts *opts, Error **errp);
BlockDriverState *bdrv_new(const char *device_name, Error **errp); BlockDriverState *bdrv_new(const char *device_name, Error **errp);
void bdrv_make_anon(BlockDriverState *bs); void bdrv_make_anon(BlockDriverState *bs);
void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old); void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old);
@ -312,7 +312,8 @@ typedef enum {
int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix); 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 */ /* external snapshots */
bool bdrv_recurse_is_first_non_filter(BlockDriverState *bs, bool bdrv_recurse_is_first_non_filter(BlockDriverState *bs,

View File

@ -118,6 +118,8 @@ struct BlockDriver {
void (*bdrv_rebind)(BlockDriverState *bs); void (*bdrv_rebind)(BlockDriverState *bs);
int (*bdrv_create)(const char *filename, QEMUOptionParameter *options, int (*bdrv_create)(const char *filename, QEMUOptionParameter *options,
Error **errp); 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_set_key)(BlockDriverState *bs, const char *key);
int (*bdrv_make_empty)(BlockDriverState *bs); int (*bdrv_make_empty)(BlockDriverState *bs);
/* aio */ /* aio */
@ -217,7 +219,12 @@ struct BlockDriver {
/* List of options for creating images, terminated by name == NULL */ /* List of options for creating images, terminated by name == NULL */
QEMUOptionParameter *create_options; 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. * Returns 0 for completed check, -errno for internal errors.
@ -228,6 +235,10 @@ struct BlockDriver {
int (*bdrv_amend_options)(BlockDriverState *bs, int (*bdrv_amend_options)(BlockDriverState *bs,
QEMUOptionParameter *options); 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); void (*bdrv_debug_event)(BlockDriverState *bs, BlkDebugEvent event);

View File

@ -271,7 +271,7 @@ static int read_password(char *buf, int buf_size)
static int print_block_option_help(const char *filename, const char *fmt) static int print_block_option_help(const char *filename, const char *fmt)
{ {
BlockDriver *drv, *proto_drv; BlockDriver *drv, *proto_drv;
QEMUOptionParameter *create_options = NULL; QemuOptsList *create_opts = NULL;
/* Find driver and parse its options */ /* Find driver and parse its options */
drv = bdrv_find_format(fmt); drv = bdrv_find_format(fmt);
@ -280,22 +280,21 @@ static int print_block_option_help(const char *filename, const char *fmt)
return 1; return 1;
} }
create_options = append_option_parameters(create_options, create_opts = qemu_opts_append(create_opts, drv->create_opts,
drv->create_options); drv->create_options);
if (filename) { if (filename) {
proto_drv = bdrv_find_protocol(filename, true); proto_drv = bdrv_find_protocol(filename, true);
if (!proto_drv) { if (!proto_drv) {
error_report("Unknown protocol '%s'", filename); error_report("Unknown protocol '%s'", filename);
free_option_parameters(create_options); qemu_opts_free(create_opts);
return 1; return 1;
} }
create_options = append_option_parameters(create_options, create_opts = qemu_opts_append(create_opts, proto_drv->create_opts,
proto_drv->create_options); proto_drv->create_options);
} }
print_option_help(create_options); qemu_opts_print_help(create_opts);
free_option_parameters(create_options); qemu_opts_free(create_opts);
return 0; return 0;
} }
@ -349,19 +348,19 @@ fail:
return NULL; 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_filename,
const char *base_fmt) const char *base_fmt)
{ {
if (base_filename) { 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'", error_report("Backing file not supported for file format '%s'",
fmt); fmt);
return -1; return -1;
} }
} }
if (base_fmt) { 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 " error_report("Backing file format not supported for file "
"format '%s'", fmt); "format '%s'", fmt);
return -1; return -1;
@ -1191,8 +1190,9 @@ static int img_convert(int argc, char **argv)
size_t bufsectors = IO_BUF_SIZE / BDRV_SECTOR_SIZE; size_t bufsectors = IO_BUF_SIZE / BDRV_SECTOR_SIZE;
const uint8_t *buf1; const uint8_t *buf1;
BlockDriverInfo bdi; BlockDriverInfo bdi;
QEMUOptionParameter *param = NULL, *create_options = NULL; QemuOpts *opts = NULL;
QEMUOptionParameter *out_baseimg_param; QemuOptsList *create_opts = NULL;
const char *out_baseimg_param;
char *options = NULL; char *options = NULL;
const char *snapshot_name = NULL; const char *snapshot_name = NULL;
int min_sparse = 8; /* Need at least 4k of zeros for sparse detection */ int min_sparse = 8; /* Need at least 4k of zeros for sparse detection */
@ -1381,40 +1381,36 @@ static int img_convert(int argc, char **argv)
goto out; goto out;
} }
create_options = append_option_parameters(create_options, create_opts = qemu_opts_append(create_opts, drv->create_opts,
drv->create_options); drv->create_options);
create_options = append_option_parameters(create_options, create_opts = qemu_opts_append(create_opts, proto_drv->create_opts,
proto_drv->create_options); proto_drv->create_options);
if (options) { opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
param = parse_option_parameters(options, create_options, param); if (options && qemu_opts_do_parse(opts, options, NULL)) {
if (param == NULL) { error_report("Invalid options for file format '%s'", out_fmt);
error_report("Invalid options for file format '%s'.", out_fmt); ret = -1;
ret = -1; goto out;
goto out;
}
} else {
param = parse_option_parameters("", create_options, param);
} }
set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512); qemu_opt_set_number(opts, BLOCK_OPT_SIZE, total_sectors * 512);
ret = add_old_style_options(out_fmt, param, out_baseimg, NULL); ret = add_old_style_options(out_fmt, opts, out_baseimg, NULL);
if (ret < 0) { if (ret < 0) {
goto out; goto out;
} }
/* Get backing file name if -o backing_file was used */ /* 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) { if (out_baseimg_param) {
out_baseimg = out_baseimg_param->value.s; out_baseimg = out_baseimg_param;
} }
/* Check if compression is supported */ /* Check if compression is supported */
if (compress) { if (compress) {
QEMUOptionParameter *encryption = bool encryption =
get_option_parameter(param, BLOCK_OPT_ENCRYPT); qemu_opt_get_bool(opts, BLOCK_OPT_ENCRYPT, false);
QEMUOptionParameter *preallocation = const char *preallocation =
get_option_parameter(param, BLOCK_OPT_PREALLOC); qemu_opt_get(opts, BLOCK_OPT_PREALLOC);
if (!drv->bdrv_write_compressed) { if (!drv->bdrv_write_compressed) {
error_report("Compression not supported for this file format"); error_report("Compression not supported for this file format");
@ -1422,15 +1418,15 @@ static int img_convert(int argc, char **argv)
goto out; goto out;
} }
if (encryption && encryption->value.n) { if (encryption) {
error_report("Compression and encryption not supported at " error_report("Compression and encryption not supported at "
"the same time"); "the same time");
ret = -1; ret = -1;
goto out; goto out;
} }
if (preallocation && preallocation->value.s if (preallocation
&& strcmp(preallocation->value.s, "off")) && strcmp(preallocation, "off"))
{ {
error_report("Compression and preallocation not supported at " error_report("Compression and preallocation not supported at "
"the same time"); "the same time");
@ -1441,7 +1437,7 @@ static int img_convert(int argc, char **argv)
if (!skip_create) { if (!skip_create) {
/* Create the new image */ /* 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) { if (ret < 0) {
error_report("%s: error while converting %s: %s", error_report("%s: error while converting %s: %s",
out_filename, out_fmt, error_get_pretty(local_err)); out_filename, out_fmt, error_get_pretty(local_err));
@ -1706,8 +1702,8 @@ out:
qemu_progress_print(100, 0); qemu_progress_print(100, 0);
} }
qemu_progress_end(); qemu_progress_end();
free_option_parameters(create_options); qemu_opts_del(opts);
free_option_parameters(param); qemu_opts_free(create_opts);
qemu_vfree(buf); qemu_vfree(buf);
if (sn_opts) { if (sn_opts) {
qemu_opts_del(sn_opts); qemu_opts_del(sn_opts);
@ -2698,7 +2694,8 @@ static int img_amend(int argc, char **argv)
{ {
int c, ret = 0; int c, ret = 0;
char *options = NULL; char *options = NULL;
QEMUOptionParameter *create_options = NULL, *options_param = NULL; QemuOptsList *create_opts = NULL;
QemuOpts *opts = NULL;
const char *fmt = NULL, *filename; const char *fmt = NULL, *filename;
bool quiet = false; bool quiet = false;
BlockDriverState *bs = NULL; BlockDriverState *bs = NULL;
@ -2769,17 +2766,16 @@ static int img_amend(int argc, char **argv)
goto out; goto out;
} }
create_options = append_option_parameters(create_options, create_opts = qemu_opts_append(create_opts, bs->drv->create_opts,
bs->drv->create_options); bs->drv->create_options);
options_param = parse_option_parameters(options, create_options, opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
options_param); if (options && qemu_opts_do_parse(opts, options, NULL)) {
if (options_param == NULL) {
error_report("Invalid options for file format '%s'", fmt); error_report("Invalid options for file format '%s'", fmt);
ret = -1; ret = -1;
goto out; goto out;
} }
ret = bdrv_amend_options(bs, options_param); ret = bdrv_amend_options(bs, NULL, opts);
if (ret < 0) { if (ret < 0) {
error_report("Error while amending options: %s", strerror(-ret)); error_report("Error while amending options: %s", strerror(-ret));
goto out; goto out;
@ -2789,8 +2785,8 @@ out:
if (bs) { if (bs) {
bdrv_unref(bs); bdrv_unref(bs);
} }
free_option_parameters(create_options); qemu_opts_del(opts);
free_option_parameters(options_param); qemu_opts_free(create_opts);
g_free(options); g_free(options);
if (ret) { if (ret) {

View File

@ -120,7 +120,7 @@ qemu-img: kilobytes, megabytes, gigabytes, terabytes, petabytes and exabytes.
qemu-img create -f qcow2 -o size=foobar TEST_DIR/t.qcow2 qemu-img create -f qcow2 -o size=foobar TEST_DIR/t.qcow2
qemu-img: Parameter 'size' expects a size 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 == == Check correct interpretation of suffixes for cluster size ==

View File

@ -281,7 +281,7 @@ Lazy refcounts only supported with compatibility level 1.1 and above (use compat
qemu-img: Error while amending options: Invalid argument qemu-img: Error while amending options: Invalid argument
Unknown compatibility level 0.42. Unknown compatibility level 0.42.
qemu-img: Error while amending options: Invalid argument qemu-img: Error while amending options: Invalid argument
Unknown option 'foo' qemu-img: Invalid parameter 'foo'
qemu-img: Invalid options for file format 'qcow2' qemu-img: Invalid options for file format 'qcow2'
Changing the cluster size is not supported. Changing the cluster size is not supported.
qemu-img: Error while amending options: Operation not supported qemu-img: Error while amending options: Operation not supported