diff options
author | Kevin Wolf <kwolf@redhat.com> | 2016-05-17 14:51:55 +0200 |
---|---|---|
committer | Kevin Wolf <kwolf@redhat.com> | 2016-05-25 19:04:10 +0200 |
commit | 36fe13317bfc3414745528c6c08cea2904ca49ec (patch) | |
tree | 5c0d2dab6123311014f8b5e3bae6e9528859e21b /block.c | |
parent | 6820643fdbe0d4e2ab6a188dee4782c003a4bb68 (diff) | |
download | qemu-36fe13317bfc3414745528c6c08cea2904ca49ec.zip qemu-36fe13317bfc3414745528c6c08cea2904ca49ec.tar.gz qemu-36fe13317bfc3414745528c6c08cea2904ca49ec.tar.bz2 |
block: Fix reconfiguring graph with drained nodes
When changing the BlockDriverState that a BdrvChild points to while the
node is currently drained, we must call the .drained_end() parent
callback. Conversely, when this means attaching a new node that is
already drained, we need to call .drained_begin().
bdrv_root_attach_child() takes now an opaque parameter, which is needed
because the callbacks must also be called if we're attaching a new child
to the BlockBackend when the root node is already drained, and they need
a way to identify the BlockBackend. Previously, child->opaque was set
too late and the callbacks would still see it as NULL.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Diffstat (limited to 'block.c')
-rw-r--r-- | block.c | 18 |
1 files changed, 14 insertions, 4 deletions
@@ -1155,24 +1155,33 @@ static void bdrv_replace_child(BdrvChild *child, BlockDriverState *new_bs) BlockDriverState *old_bs = child->bs; if (old_bs) { + if (old_bs->quiesce_counter && child->role->drained_end) { + child->role->drained_end(child); + } QLIST_REMOVE(child, next_parent); } + + child->bs = new_bs; + if (new_bs) { QLIST_INSERT_HEAD(&new_bs->parents, child, next_parent); + if (new_bs->quiesce_counter && child->role->drained_begin) { + child->role->drained_begin(child); + } } - - child->bs = new_bs; } BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs, const char *child_name, - const BdrvChildRole *child_role) + const BdrvChildRole *child_role, + void *opaque) { BdrvChild *child = g_new(BdrvChild, 1); *child = (BdrvChild) { .bs = NULL, .name = g_strdup(child_name), .role = child_role, + .opaque = opaque, }; bdrv_replace_child(child, child_bs); @@ -1185,7 +1194,8 @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs, const char *child_name, const BdrvChildRole *child_role) { - BdrvChild *child = bdrv_root_attach_child(child_bs, child_name, child_role); + BdrvChild *child = bdrv_root_attach_child(child_bs, child_name, child_role, + NULL); QLIST_INSERT_HEAD(&parent_bs->children, child, next); return child; } |