- qemu_migration: Refactor qemuMigrationSrcRestoreDomainState (RHEL-79168) - qemu_migration: Do not automatically resume domain after I/O error (RHEL-79168) - qemucapabilitiestest: Add data for the qemu-10.0 dev cycle on x86_64 (RHEL-79095) - qemucapabilitiestest: Update 'caps_10.0.0_x86_64' to 'v9.2.0-1636-gffaf7f0376' (RHEL-79095) - qemu: capabilies: Introduce QEMU_CAPS_BLOCKDEV_SET_ACTIVE (RHEL-79095) - qemu: monitor: Add monitor backend for 'blockdev-set-active' (RHEL-79095) - qemu: migration: Reactivate block nodes after migration if VM is left paused (RHEL-79095) - conf: change virDomainHostdevInsert() to return void (RHEL-69455) - qemu: fix qemu validation to forbid guest-side IP address for type='vdpa' (RHEL-69455) - qemu: validate that model is virtio for vhostuser and vdpa interfaces in the same place (RHEL-69455) - qemu: automatically set model type='virtio' for interface type='vhostuser' (RHEL-69455) - qemu: do all vhostuser attribute validation in qemu driver (RHEL-69455) - conf/qemu: make <source> element *almost* optional for type=vhostuser (RHEL-69455) - qemu: use switch instead of if in qemuProcessPrepareDomainNetwork() (RHEL-69455) - qemu: make qemuPasstCreateSocketPath() public (RHEL-69455) - qemu: complete vhostuser + passt support (RHEL-69455) - qemu: fail validation if a domain def has vhostuser/passt but no shared mem (RHEL-69455) - docs: improve type='user' docs to higlight differences between SLIRP and passt (RHEL-69455) - docs: document using passt backend with <interface type='vhostuser'> (RHEL-69455) - utils: Canonicalize paths before comparing them (RHEL-79166) Resolves: RHEL-69455, RHEL-79095, RHEL-79166, RHEL-79168
140 lines
4.7 KiB
Diff
140 lines
4.7 KiB
Diff
From 64a914839cf44c7ed309fb827ab40c94dcb7c0d0 Mon Sep 17 00:00:00 2001
|
|
Message-ID: <64a914839cf44c7ed309fb827ab40c94dcb7c0d0.1739824249.git.jdenemar@redhat.com>
|
|
From: Peter Krempa <pkrempa@redhat.com>
|
|
Date: Mon, 10 Feb 2025 19:49:10 +0100
|
|
Subject: [PATCH] qemu: migration: Reactivate block nodes after migration if VM
|
|
is left paused
|
|
|
|
On incoming migration qemu doesn't activate the block graph nodes right
|
|
away. This is to properly facilitate locking of the images.
|
|
|
|
The block nodes are normally re-activated when starting the CPUs after
|
|
migration, but in cases (e.g. when a paused VM was migrated) when the VM
|
|
is left paused the block nodes are not re-activated by qemu.
|
|
|
|
This means that blockjobs which would want to write to an existing
|
|
backing chain member would fail. Generally read-only jobs would succeed
|
|
with older qemu's but this was not intended.
|
|
|
|
Instead with new qemu you'll always get an error if attempting to access
|
|
a inactive node:
|
|
|
|
error: internal error: unable to execute QEMU command 'blockdev-mirror': Inactive 'libvirt-1-storage' can't be a backing child of active '#block052'
|
|
|
|
This is the case for explicit blockjobs (virsh blockcopy) but also for
|
|
non shared-storage migration (virsh migrate --copy-storage-all).
|
|
|
|
Since qemu now provides 'blockdev-set-active' QMP command which can
|
|
on-demand re-activate the nodes we can re-activate them in similar cases
|
|
as when we'd be starting vCPUs if the VM weren't left paused.
|
|
|
|
The only exception is on the source in case of a failed post-copy
|
|
migration as the VM already ran on destination so it won't ever run on
|
|
the source even when recovered.
|
|
|
|
Resolves: https://issues.redhat.com/browse/RHEL-78398
|
|
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
|
|
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
|
|
(cherry picked from commit 2626fa0569781c0f42db247f4b7116c33cd88b43)
|
|
|
|
https://issues.redhat.com/browse/RHEL-79095
|
|
---
|
|
src/qemu/qemu_migration.c | 55 ++++++++++++++++++++++++++++++++++++---
|
|
1 file changed, 52 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
|
|
index 4112e95a1e..62da892254 100644
|
|
--- a/src/qemu/qemu_migration.c
|
|
+++ b/src/qemu/qemu_migration.c
|
|
@@ -220,6 +220,43 @@ qemuMigrationSrcStoreDomainState(virDomainObj *vm)
|
|
}
|
|
|
|
|
|
+/**
|
|
+ * qemuMigrationBlockNodesReactivate:
|
|
+ *
|
|
+ * In case when we're keeping the VM paused qemu will not re-activate the block
|
|
+ * device backend tree so blockjobs would fail. In case when qemu supports the
|
|
+ * 'blockdev-set-active' command this function will re-activate the block nodes.
|
|
+ */
|
|
+static void
|
|
+qemuMigrationBlockNodesReactivate(virDomainObj *vm,
|
|
+ virDomainAsyncJob asyncJob)
|
|
+{
|
|
+ virErrorPtr orig_err;
|
|
+ qemuDomainObjPrivate *priv = vm->privateData;
|
|
+ int rc;
|
|
+
|
|
+ if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV_SET_ACTIVE))
|
|
+ return;
|
|
+
|
|
+ VIR_DEBUG("re-activating block nodes");
|
|
+
|
|
+ virErrorPreserveLast(&orig_err);
|
|
+
|
|
+ if (qemuDomainObjEnterMonitorAsync(vm, asyncJob) < 0)
|
|
+ goto cleanup;
|
|
+
|
|
+ rc = qemuMonitorBlockdevSetActive(priv->mon, NULL, true);
|
|
+
|
|
+ qemuDomainObjExitMonitor(vm);
|
|
+
|
|
+ if (rc < 0)
|
|
+ VIR_WARN("failed to re-activate block nodes after migration of VM '%s'", vm->def->name);
|
|
+
|
|
+ cleanup:
|
|
+ virErrorRestore(&orig_err);
|
|
+}
|
|
+
|
|
+
|
|
static void
|
|
qemuMigrationSrcRestoreDomainState(virQEMUDriver *driver, virDomainObj *vm)
|
|
{
|
|
@@ -236,14 +273,17 @@ qemuMigrationSrcRestoreDomainState(virQEMUDriver *driver, virDomainObj *vm)
|
|
virDomainStateTypeToString(state),
|
|
virDomainStateReasonToString(state, reason));
|
|
|
|
- if (preMigrationState != VIR_DOMAIN_RUNNING ||
|
|
- state != VIR_DOMAIN_PAUSED ||
|
|
+ if (state == VIR_DOMAIN_PAUSED &&
|
|
reason == VIR_DOMAIN_PAUSED_POSTCOPY_FAILED)
|
|
return;
|
|
|
|
+ if (preMigrationState != VIR_DOMAIN_RUNNING ||
|
|
+ state != VIR_DOMAIN_PAUSED)
|
|
+ goto reactivate;
|
|
+
|
|
if (reason == VIR_DOMAIN_PAUSED_IOERROR) {
|
|
VIR_DEBUG("Domain is paused due to I/O error, skipping resume");
|
|
- return;
|
|
+ goto reactivate;
|
|
}
|
|
|
|
VIR_DEBUG("Restoring pre-migration state due to migration error");
|
|
@@ -266,7 +306,14 @@ qemuMigrationSrcRestoreDomainState(virQEMUDriver *driver, virDomainObj *vm)
|
|
VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR);
|
|
virObjectEventStateQueue(driver->domainEventState, event);
|
|
}
|
|
+
|
|
+ goto reactivate;
|
|
}
|
|
+
|
|
+ return;
|
|
+
|
|
+ reactivate:
|
|
+ qemuMigrationBlockNodesReactivate(vm, VIR_ASYNC_JOB_MIGRATION_OUT);
|
|
}
|
|
|
|
|
|
@@ -6781,6 +6828,8 @@ qemuMigrationDstFinishFresh(virQEMUDriver *driver,
|
|
|
|
if (*inPostCopy)
|
|
*doKill = false;
|
|
+ } else {
|
|
+ qemuMigrationBlockNodesReactivate(vm, VIR_ASYNC_JOB_MIGRATION_IN);
|
|
}
|
|
|
|
if (mig->jobData) {
|
|
--
|
|
2.48.1
|