aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>2020-01-21 17:28:01 +0300
committerMax Reitz <mreitz@redhat.com>2020-02-06 13:47:45 +0100
commit0df62f45c1de6c020f1e6fba4eeafd248209b003 (patch)
tree4013a0cb0ed58a50709235cfce09d68a88b042df
parent3afea40243d7ccba7b569daa4dc7b174e594f792 (diff)
block/backup-top: fix failure path
We can't access top after call bdrv_backup_top_drop, as it is already freed at this time. Also, no needs to unref target child by hand, it will be unrefed on bdrv_close() automatically. So, just do bdrv_backup_top_drop if append succeed and one bdrv_unref otherwise. Note, that in !appended case bdrv_unref(top) moved into drained section on source. It doesn't really matter, but just for code simplicity. Fixes: 7df7868b96404 Cc: qemu-stable@nongnu.org # v4.2.0 Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> Reviewed-by: Max Reitz <mreitz@redhat.com> Message-id: 20200121142802.21467-2-vsementsov@virtuozzo.com Signed-off-by: Max Reitz <mreitz@redhat.com>
-rw-r--r--block/backup-top.c21
1 files changed, 12 insertions, 9 deletions
diff --git a/block/backup-top.c b/block/backup-top.c
index 9aed2eb4c0..fa78f3256d 100644
--- a/block/backup-top.c
+++ b/block/backup-top.c
@@ -190,6 +190,7 @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
BlockDriverState *top = bdrv_new_open_driver(&bdrv_backup_top_filter,
filter_node_name,
BDRV_O_RDWR, errp);
+ bool appended = false;
if (!top) {
return NULL;
@@ -212,8 +213,9 @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
bdrv_append(top, source, &local_err);
if (local_err) {
error_prepend(&local_err, "Cannot append backup-top filter: ");
- goto append_failed;
+ goto fail;
}
+ appended = true;
/*
* bdrv_append() finished successfully, now we can require permissions
@@ -224,14 +226,14 @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
if (local_err) {
error_prepend(&local_err,
"Cannot set permissions for backup-top filter: ");
- goto failed_after_append;
+ goto fail;
}
state->bcs = block_copy_state_new(top->backing, state->target,
cluster_size, write_flags, &local_err);
if (local_err) {
error_prepend(&local_err, "Cannot create block-copy-state: ");
- goto failed_after_append;
+ goto fail;
}
*bcs = state->bcs;
@@ -239,14 +241,15 @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
return top;
-failed_after_append:
- state->active = false;
- bdrv_backup_top_drop(top);
+fail:
+ if (appended) {
+ state->active = false;
+ bdrv_backup_top_drop(top);
+ } else {
+ bdrv_unref(top);
+ }
-append_failed:
bdrv_drained_end(source);
- bdrv_unref_child(top, state->target);
- bdrv_unref(top);
error_propagate(errp, local_err);
return NULL;