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: 7df7868b96
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>
(cherry picked from commit 0df62f45c1)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
stable-4.2
Vladimir Sementsov-Ogievskiy 2020-01-21 17:28:01 +03:00 committed by Michael Roth
parent a967e75f3a
commit e92b21ffc4
1 changed files with 12 additions and 9 deletions

View File

@ -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;