aboutsummaryrefslogtreecommitdiff
path: root/block.c
diff options
context:
space:
mode:
Diffstat (limited to 'block.c')
-rw-r--r--block.c46
1 files changed, 34 insertions, 12 deletions
diff --git a/block.c b/block.c
index 39f373e035..6161dbe3eb 100644
--- a/block.c
+++ b/block.c
@@ -2584,6 +2584,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
BlockBackend *file = NULL;
BlockDriverState *bs;
BlockDriver *drv = NULL;
+ BdrvChild *child;
const char *drvname;
const char *backing;
Error *local_err = NULL;
@@ -2767,6 +2768,15 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
}
}
+ /* Remove all children options from bs->options and bs->explicit_options */
+ QLIST_FOREACH(child, &bs->children, next) {
+ char *child_key_dot;
+ child_key_dot = g_strdup_printf("%s.", child->name);
+ qdict_extract_subqdict(bs->explicit_options, NULL, child_key_dot);
+ qdict_extract_subqdict(bs->options, NULL, child_key_dot);
+ g_free(child_key_dot);
+ }
+
bdrv_refresh_filename(bs);
/* Check if any unknown options were used */
@@ -2976,6 +2986,7 @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
}
child_key_dot = g_strdup_printf("%s.", child->name);
+ qdict_extract_subqdict(explicit_options, NULL, child_key_dot);
qdict_extract_subqdict(options, &new_child_options, child_key_dot);
g_free(child_key_dot);
@@ -3039,12 +3050,13 @@ int bdrv_reopen_multiple(AioContext *ctx, BlockReopenQueue *bs_queue, Error **er
cleanup:
QSIMPLEQ_FOREACH_SAFE(bs_entry, bs_queue, entry, next) {
- if (ret && bs_entry->prepared) {
- bdrv_reopen_abort(&bs_entry->state);
- } else if (ret) {
+ if (ret) {
+ if (bs_entry->prepared) {
+ bdrv_reopen_abort(&bs_entry->state);
+ }
qobject_unref(bs_entry->state.explicit_options);
+ qobject_unref(bs_entry->state.options);
}
- qobject_unref(bs_entry->state.options);
g_free(bs_entry);
}
g_free(bs_queue);
@@ -3144,6 +3156,7 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
Error *local_err = NULL;
BlockDriver *drv;
QemuOpts *opts;
+ QDict *orig_reopen_opts;
const char *value;
bool read_only;
@@ -3151,6 +3164,11 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
assert(reopen_state->bs->drv != NULL);
drv = reopen_state->bs->drv;
+ /* This function and each driver's bdrv_reopen_prepare() remove
+ * entries from reopen_state->options as they are processed, so
+ * we need to make a copy of the original QDict. */
+ orig_reopen_opts = qdict_clone_shallow(reopen_state->options);
+
/* Process generic block layer options */
opts = qemu_opts_create(&bdrv_runtime_opts, NULL, 0, &error_abort);
qemu_opts_absorb_qdict(opts, reopen_state->options, &local_err);
@@ -3257,8 +3275,13 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
ret = 0;
+ /* Restore the original reopen_state->options QDict */
+ qobject_unref(reopen_state->options);
+ reopen_state->options = qobject_ref(orig_reopen_opts);
+
error:
qemu_opts_del(opts);
+ qobject_unref(orig_reopen_opts);
return ret;
}
@@ -3288,8 +3311,10 @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state)
/* set BDS specific flags now */
qobject_unref(bs->explicit_options);
+ qobject_unref(bs->options);
bs->explicit_options = reopen_state->explicit_options;
+ bs->options = reopen_state->options;
bs->open_flags = reopen_state->flags;
bs->read_only = !(reopen_state->flags & BDRV_O_RDWR);
@@ -3330,8 +3355,6 @@ void bdrv_reopen_abort(BDRVReopenState *reopen_state)
drv->bdrv_reopen_abort(reopen_state);
}
- qobject_unref(reopen_state->explicit_options);
-
bdrv_abort_perm_update(reopen_state->bs);
}
@@ -3349,7 +3372,9 @@ static void bdrv_close(BlockDriverState *bs)
bdrv_drain(bs); /* in case flush left pending I/O */
if (bs->drv) {
- bs->drv->bdrv_close(bs);
+ if (bs->drv->bdrv_close) {
+ bs->drv->bdrv_close(bs);
+ }
bs->drv = NULL;
}
@@ -5125,16 +5150,13 @@ static bool append_open_options(QDict *d, BlockDriverState *bs)
QemuOptDesc *desc;
BdrvChild *child;
bool found_any = false;
- const char *p;
for (entry = qdict_first(bs->options); entry;
entry = qdict_next(bs->options, entry))
{
- /* Exclude options for children */
+ /* Exclude node-name references to children */
QLIST_FOREACH(child, &bs->children, next) {
- if (strstart(qdict_entry_key(entry), child->name, &p)
- && (!*p || *p == '.'))
- {
+ if (!strcmp(entry->key, child->name)) {
break;
}
}