aboutsummaryrefslogtreecommitdiff
path: root/blockdev.c
diff options
context:
space:
mode:
authorKevin Wolf <kwolf@redhat.com>2017-02-20 12:46:42 +0100
committerKevin Wolf <kwolf@redhat.com>2017-02-28 20:47:51 +0100
commitb2c2832c6140cfe3ddc0de2d77eeb0b77dea8fd3 (patch)
treea8887134fb47b8dbd8c23a0cd4da55bc979ecbbb /blockdev.c
parent12fa4af61fb2a08b156134c3b6717534c637c995 (diff)
block: Add Error parameter to bdrv_append()
Aborting on error in bdrv_append() isn't correct. This patch fixes it and lets the callers handle failures. Test case 085 needs a reference output update. This is caused by the reversed order of bdrv_set_backing_hd() and change_parent_backing_link() in bdrv_append(): When the backing file of the new node is set, the parent nodes are still pointing to the old top, so the backing blocker is now initialised with the node name rather than the BlockBackend name. Signed-off-by: Kevin Wolf <kwolf@redhat.com> Acked-by: Fam Zheng <famz@redhat.com> Reviewed-by: Max Reitz <mreitz@redhat.com>
Diffstat (limited to 'blockdev.c')
-rw-r--r--blockdev.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/blockdev.c b/blockdev.c
index ff781d9df3..8eb4e84fe0 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1768,6 +1768,17 @@ static void external_snapshot_prepare(BlkActionState *common,
if (!state->new_bs->drv->supports_backing) {
error_setg(errp, "The snapshot does not support backing images");
+ return;
+ }
+
+ /* This removes our old bs and adds the new bs. This is an operation that
+ * can fail, so we need to do it in .prepare; undoing it for abort is
+ * always possible. */
+ bdrv_ref(state->new_bs);
+ bdrv_append(state->new_bs, state->old_bs, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
}
}
@@ -1778,8 +1789,6 @@ static void external_snapshot_commit(BlkActionState *common)
bdrv_set_aio_context(state->new_bs, state->aio_context);
- /* This removes our old bs and adds the new bs */
- bdrv_append(state->new_bs, state->old_bs);
/* We don't need (or want) to use the transactional
* bdrv_reopen_multiple() across all the entries at once, because we
* don't want to abort all of them if one of them fails the reopen */
@@ -1794,7 +1803,9 @@ static void external_snapshot_abort(BlkActionState *common)
ExternalSnapshotState *state =
DO_UPCAST(ExternalSnapshotState, common, common);
if (state->new_bs) {
- bdrv_unref(state->new_bs);
+ if (state->new_bs->backing) {
+ bdrv_replace_in_backing_chain(state->new_bs, state->old_bs);
+ }
}
}
@@ -1805,6 +1816,7 @@ static void external_snapshot_clean(BlkActionState *common)
if (state->aio_context) {
bdrv_drained_end(state->old_bs);
aio_context_release(state->aio_context);
+ bdrv_unref(state->new_bs);
}
}