aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block.c57
1 files changed, 40 insertions, 17 deletions
diff --git a/block.c b/block.c
index c204d13106..2c41fffc9f 100644
--- a/block.c
+++ b/block.c
@@ -817,6 +817,11 @@ static QemuOptsList bdrv_runtime_opts = {
.type = QEMU_OPT_STRING,
.help = "Node name of the block device node",
},
+ {
+ .name = "driver",
+ .type = QEMU_OPT_STRING,
+ .help = "Block driver to use for the node",
+ },
{ /* end of list */ }
},
};
@@ -827,18 +832,31 @@ static QemuOptsList bdrv_runtime_opts = {
* Removes all processed options from *options.
*/
static int bdrv_open_common(BlockDriverState *bs, BdrvChild *file,
- QDict *options, int flags, BlockDriver *drv, Error **errp)
+ QDict *options, int flags, Error **errp)
{
int ret, open_flags;
const char *filename;
+ const char *driver_name = NULL;
const char *node_name = NULL;
QemuOpts *opts;
+ BlockDriver *drv;
Error *local_err = NULL;
- assert(drv != NULL);
assert(bs->file == NULL);
assert(options != NULL && bs->options != options);
+ opts = qemu_opts_create(&bdrv_runtime_opts, NULL, 0, &error_abort);
+ qemu_opts_absorb_qdict(opts, options, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ ret = -EINVAL;
+ goto fail_opts;
+ }
+
+ driver_name = qemu_opt_get(opts, "driver");
+ drv = bdrv_find_format(driver_name);
+ assert(drv != NULL);
+
if (file != NULL) {
filename = file->bs->filename;
} else {
@@ -848,19 +866,12 @@ static int bdrv_open_common(BlockDriverState *bs, BdrvChild *file,
if (drv->bdrv_needs_filename && !filename) {
error_setg(errp, "The '%s' block driver requires a file name",
drv->format_name);
- return -EINVAL;
- }
-
- trace_bdrv_open_common(bs, filename ?: "", flags, drv->format_name);
-
- opts = qemu_opts_create(&bdrv_runtime_opts, NULL, 0, &error_abort);
- qemu_opts_absorb_qdict(opts, options, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
ret = -EINVAL;
goto fail_opts;
}
+ trace_bdrv_open_common(bs, filename ?: "", flags, drv->format_name);
+
node_name = qemu_opt_get(opts, "node-name");
bdrv_assign_node_name(bs, node_name, &local_err);
if (local_err) {
@@ -1477,11 +1488,14 @@ static int bdrv_open_inherit(BlockDriverState **pbs, const char *filename,
goto fail;
}
+ bs->open_flags = flags;
+ bs->options = options;
+ options = qdict_clone_shallow(options);
+
/* Find the right image format driver */
drvname = qdict_get_try_str(options, "driver");
if (drvname) {
drv = bdrv_find_format(drvname);
- qdict_del(options, "driver");
if (!drv) {
error_setg(errp, "Unknown driver: '%s'", drvname);
ret = -EINVAL;
@@ -1497,10 +1511,6 @@ static int bdrv_open_inherit(BlockDriverState **pbs, const char *filename,
qdict_del(options, "backing");
}
- bs->open_flags = flags;
- bs->options = options;
- options = qdict_clone_shallow(options);
-
/* Open image file without format layer */
if ((flags & BDRV_O_PROTOCOL) == 0) {
if (flags & BDRV_O_RDWR) {
@@ -1528,6 +1538,19 @@ static int bdrv_open_inherit(BlockDriverState **pbs, const char *filename,
if (ret < 0) {
goto fail;
}
+ /*
+ * This option update would logically belong in bdrv_fill_options(),
+ * but we first need to open bs->file for the probing to work, while
+ * opening bs->file already requires the (mostly) final set of options
+ * so that cache mode etc. can be inherited.
+ *
+ * Adding the driver later is somewhat ugly, but it's not an option
+ * that would ever be inherited, so it's correct. We just need to make
+ * sure to update both bs->options (which has the full effective
+ * options for bs) and options (which has file.* already removed).
+ */
+ qdict_put(bs->options, "driver", qstring_from_str(drv->format_name));
+ qdict_put(options, "driver", qstring_from_str(drv->format_name));
} else if (!drv) {
error_setg(errp, "Must specify either driver or file");
ret = -EINVAL;
@@ -1541,7 +1564,7 @@ static int bdrv_open_inherit(BlockDriverState **pbs, const char *filename,
assert(!(flags & BDRV_O_PROTOCOL) || !file);
/* Open the image */
- ret = bdrv_open_common(bs, file, options, flags, drv, &local_err);
+ ret = bdrv_open_common(bs, file, options, flags, &local_err);
if (ret < 0) {
goto fail;
}