92 lines
3.0 KiB
Diff
92 lines
3.0 KiB
Diff
|
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
||
|
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 <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>
|
||
|
Signed-off-by: Bruce Rogers <brogers@suse.com>
|
||
|
---
|
||
|
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;
|