aboutsummaryrefslogtreecommitdiff
path: root/block/mirror.c
diff options
context:
space:
mode:
authorKevin Wolf <kwolf@redhat.com>2015-09-14 15:33:33 +0200
committerKevin Wolf <kwolf@redhat.com>2015-10-16 15:34:29 +0200
commit5db15a57697063b9062a015dbc6d5d38211f2df1 (patch)
tree37f131976de33ffd0e9a17c885d5e88bab3f3096 /block/mirror.c
parent760e006384ecd5b8b8b1b91b5c85ff8fdcb3a21f (diff)
block: Manage backing file references in bdrv_set_backing_hd()
This simplifies the code somewhat, especially when dropping whole backing file subchains. The exception is the mirroring code that does adventurous things with bdrv_swap() and in order to keep it working, I had to duplicate most of bdrv_set_backing_hd() locally. We'll get rid again of this ugliness shortly. Signed-off-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Alberto Garcia <berto@igalia.com> Reviewed-by: Max Reitz <mreitz@redhat.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'block/mirror.c')
-rw-r--r--block/mirror.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/block/mirror.c b/block/mirror.c
index 5d3b8bbd9c..6247b27612 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -370,10 +370,18 @@ static void mirror_exit(BlockJob *job, void *opaque)
bdrv_swap(s->target, to_replace);
if (s->common.driver->job_type == BLOCK_JOB_TYPE_COMMIT) {
/* drop the bs loop chain formed by the swap: break the loop then
- * trigger the unref from the top one */
- BlockDriverState *p = backing_bs(s->base);
- bdrv_set_backing_hd(s->base, NULL);
- bdrv_unref(p);
+ * trigger the unref */
+ /* FIXME This duplicates bdrv_set_backing_hd(), except for the
+ * actual detach/unref so that the loop can be broken. When
+ * bdrv_swap() gets replaced, this will become sane again. */
+ BlockDriverState *backing = s->base->backing->bs;
+ assert(s->base->backing_blocker);
+ bdrv_op_unblock_all(backing, s->base->backing_blocker);
+ error_free(s->base->backing_blocker);
+ s->base->backing_blocker = NULL;
+ bdrv_detach_child(s->base->backing);
+ s->base->backing = NULL;
+ bdrv_unref(backing);
}
}
if (s->to_replace) {