From: Vladimir Sementsov-Ogievskiy Date: Tue, 21 Jan 2020 17:28:01 +0300 Subject: block/backup-top: fix failure path Git-commit 0df62f45c1de6c020f1e6fba4eeafd248209b003 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 Reviewed-by: Max Reitz Message-id: 20200121142802.21467-2-vsementsov@virtuozzo.com Signed-off-by: Max Reitz Signed-off-by: Bruce Rogers --- block/backup-top.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/block/backup-top.c b/block/backup-top.c index 64e9e4f576ab27889fb4c0d8aa0a..d214139a4d2f2694df7610394003 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;