aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlberto Garcia <berto@igalia.com>2016-09-15 17:53:03 +0300
committerKevin Wolf <kwolf@redhat.com>2016-09-23 13:36:10 +0200
commit5b7ba05fe7313b03712e129a86fa70c2c215e908 (patch)
tree823ad772380ab73e20d0e23962bee032a49df851
parentf87a0e29a9814a7ab6ee92b238989fed6186c4f3 (diff)
block: Don't queue the same BDS twice in bdrv_reopen_queue_child()
bdrv_reopen_queue_child() assumes that a BlockDriverState is never added twice to BlockReopenQueue. That's however not the case: commit_start() adds 'base' (and its children) to a new reopen queue, and then 'overlay_bs' (and its children, which include 'base') to the same queue. The effect of this is that the first set of options is ignored and overriden by the second. We fixed this by swapping the order in which both BDSs were added to the queue in 3db2bd5508c86a1605258bc77c9672d93b5c350e. This patch checks if a BDS is already in the reopen queue and keeps its options. Signed-off-by: Alberto Garcia <berto@igalia.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
-rw-r--r--block.c22
1 files changed, 19 insertions, 3 deletions
diff --git a/block.c b/block.c
index b724adacfc..493ecf3137 100644
--- a/block.c
+++ b/block.c
@@ -1925,6 +1925,13 @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
options = qdict_new();
}
+ /* Check if this BlockDriverState is already in the queue */
+ QSIMPLEQ_FOREACH(bs_entry, bs_queue, entry) {
+ if (bs == bs_entry->state.bs) {
+ break;
+ }
+ }
+
/*
* Precedence of options:
* 1. Explicitly passed in options (highest)
@@ -1945,7 +1952,11 @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
}
/* Old explicitly set values (don't overwrite by inherited value) */
- old_options = qdict_clone_shallow(bs->explicit_options);
+ if (bs_entry) {
+ old_options = qdict_clone_shallow(bs_entry->state.explicit_options);
+ } else {
+ old_options = qdict_clone_shallow(bs->explicit_options);
+ }
bdrv_join_options(bs, options, old_options);
QDECREF(old_options);
@@ -1984,8 +1995,13 @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
child->role, options, flags);
}
- bs_entry = g_new0(BlockReopenQueueEntry, 1);
- QSIMPLEQ_INSERT_TAIL(bs_queue, bs_entry, entry);
+ if (!bs_entry) {
+ bs_entry = g_new0(BlockReopenQueueEntry, 1);
+ QSIMPLEQ_INSERT_TAIL(bs_queue, bs_entry, entry);
+ } else {
+ QDECREF(bs_entry->state.options);
+ QDECREF(bs_entry->state.explicit_options);
+ }
bs_entry->state.bs = bs;
bs_entry->state.options = options;