Skip to content

Commit

Permalink
block: Don't queue the same BDS twice in bdrv_reopen_queue_child()
Browse files Browse the repository at this point in the history
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 3db2bd5. 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>
  • Loading branch information
bertogg authored and kevmw committed Sep 23, 2016
1 parent f87a0e2 commit 5b7ba05
Showing 1 changed file with 19 additions and 3 deletions.
22 changes: 19 additions & 3 deletions block.c
Expand Up @@ -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)
Expand All @@ -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);

Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 5b7ba05

Please sign in to comment.