aboutsummaryrefslogtreecommitdiff
path: root/block
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
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')
-rw-r--r--block/mirror.c16
-rw-r--r--block/stream.c30
-rw-r--r--block/vvfat.c6
3 files changed, 18 insertions, 34 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) {
diff --git a/block/stream.c b/block/stream.c
index ba535c5861..3f64fa2245 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -52,34 +52,6 @@ static int coroutine_fn stream_populate(BlockDriverState *bs,
return bdrv_co_copy_on_readv(bs, sector_num, nb_sectors, &qiov);
}
-static void close_unused_images(BlockDriverState *top, BlockDriverState *base,
- const char *base_id)
-{
- BlockDriverState *intermediate;
- intermediate = backing_bs(top);
-
- /* Must assign before bdrv_delete() to prevent traversing dangling pointer
- * while we delete backing image instances.
- */
- bdrv_set_backing_hd(top, base);
-
- while (intermediate) {
- BlockDriverState *unused;
-
- /* reached base */
- if (intermediate == base) {
- break;
- }
-
- unused = intermediate;
- intermediate = backing_bs(intermediate);
- bdrv_set_backing_hd(unused, NULL);
- bdrv_unref(unused);
- }
-
- bdrv_refresh_limits(top, NULL);
-}
-
typedef struct {
int ret;
bool reached_end;
@@ -101,7 +73,7 @@ static void stream_complete(BlockJob *job, void *opaque)
}
}
data->ret = bdrv_change_backing_file(job->bs, base_id, base_fmt);
- close_unused_images(job->bs, base, base_id);
+ bdrv_set_backing_hd(job->bs, base);
}
g_free(s->backing_file_str);
diff --git a/block/vvfat.c b/block/vvfat.c
index 7c4b0f5ce4..b41055ab9d 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -2923,6 +2923,7 @@ static BlockDriver vvfat_write_target = {
static int enable_write_target(BDRVVVFATState *s, Error **errp)
{
BlockDriver *bdrv_qcow = NULL;
+ BlockDriverState *backing;
QemuOpts *opts = NULL;
int ret;
int size = sector2cluster(s, s->sector_count);
@@ -2971,7 +2972,10 @@ static int enable_write_target(BDRVVVFATState *s, Error **errp)
unlink(s->qcow_filename);
#endif
- bdrv_set_backing_hd(s->bs, bdrv_new());
+ backing = bdrv_new();
+ bdrv_set_backing_hd(s->bs, backing);
+ bdrv_unref(backing);
+
s->bs->backing->bs->drv = &vvfat_write_target;
s->bs->backing->bs->opaque = g_new(void *, 1);
*(void**)s->bs->backing->bs->opaque = s;