diff options
Diffstat (limited to 'block.c')
-rw-r--r-- | block.c | 36 |
1 files changed, 35 insertions, 1 deletions
@@ -670,14 +670,48 @@ out: int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp) { + QemuOpts *protocol_opts; BlockDriver *drv; + QDict *qdict; + int ret; drv = bdrv_find_protocol(filename, true, errp); if (drv == NULL) { return -ENOENT; } - return bdrv_create(drv, filename, opts, errp); + if (!drv->create_opts) { + error_setg(errp, "Driver '%s' does not support image creation", + drv->format_name); + return -ENOTSUP; + } + + /* + * 'opts' contains a QemuOptsList with a combination of format and protocol + * default values. + * + * The format properly removes its options, but the default values remain + * in 'opts->list'. So if the protocol has options with the same name + * (e.g. rbd has 'cluster_size' as qcow2), it will see the default values + * of the format, since for overlapping options, the format wins. + * + * To avoid this issue, lets convert QemuOpts to QDict, in this way we take + * only the set options, and then convert it back to QemuOpts, using the + * create_opts of the protocol. So the new QemuOpts, will contain only the + * protocol defaults. + */ + qdict = qemu_opts_to_qdict(opts, NULL); + protocol_opts = qemu_opts_from_qdict(drv->create_opts, qdict, errp); + if (protocol_opts == NULL) { + ret = -EINVAL; + goto out; + } + + ret = bdrv_create(drv, filename, protocol_opts, errp); +out: + qemu_opts_del(protocol_opts); + qobject_unref(qdict); + return ret; } int coroutine_fn bdrv_co_delete_file(BlockDriverState *bs, Error **errp) |