aboutsummaryrefslogtreecommitdiff
path: root/blockdev.c
diff options
context:
space:
mode:
authorKevin Wolf <kwolf@redhat.com>2025-02-04 22:13:54 +0100
committerKevin Wolf <kwolf@redhat.com>2025-02-06 14:26:51 +0100
commite80210ffb24c4e47650344ba77ce3ed354af596c (patch)
tree1d3e95b53a140278c4a015051a9c215d93e801dc /blockdev.c
parenta6490ec9d56b9e95a13918813585a3a9891710bc (diff)
downloadqemu-e80210ffb24c4e47650344ba77ce3ed354af596c.zip
qemu-e80210ffb24c4e47650344ba77ce3ed354af596c.tar.gz
qemu-e80210ffb24c4e47650344ba77ce3ed354af596c.tar.bz2
block: Inactivate external snapshot overlays when necessary
Putting an active block node on top of an inactive one is strictly speaking an invalid configuration and the next patch will turn it into a hard error. However, taking a snapshot while disk images are inactive after completing migration has an important use case: After migrating to a file, taking an external snapshot is what is needed to take a full VM snapshot. In order for this to keep working after the later patches, change creating a snapshot such that it automatically inactivates an overlay that is added on top of an already inactive node. Signed-off-by: Kevin Wolf <kwolf@redhat.com> Acked-by: Fabiano Rosas <farosas@suse.de> Reviewed-by: Eric Blake <eblake@redhat.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Message-ID: <20250204211407.381505-4-kwolf@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'blockdev.c')
-rw-r--r--blockdev.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/blockdev.c b/blockdev.c
index 2180244..eb2517f 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1497,6 +1497,22 @@ static void external_snapshot_action(TransactionAction *action,
return;
}
+ /*
+ * Older QEMU versions have allowed adding an active parent node to an
+ * inactive child node. This is unsafe in the general case, but there is an
+ * important use case, which is taking a VM snapshot with migration to file
+ * and then adding an external snapshot while the VM is still stopped and
+ * images are inactive. Requiring the user to explicitly create the overlay
+ * as inactive would break compatibility, so just do it automatically here
+ * to keep this working.
+ */
+ if (bdrv_is_inactive(state->old_bs) && !bdrv_is_inactive(state->new_bs)) {
+ ret = bdrv_inactivate(state->new_bs, errp);
+ if (ret < 0) {
+ return;
+ }
+ }
+
ret = bdrv_append(state->new_bs, state->old_bs, errp);
if (ret < 0) {
return;