[pve-devel] [RFC qemu] savevm-async: improve check for blockers
Fiona Ebner
f.ebner at proxmox.com
Fri May 17 13:39:34 CEST 2024
Same rationale as with upstream QEMU commit 5aaac46793 ("migration:
savevm: consult migration blockers"), migration and (async) snapshot
are essentially the same operation and thus snapshot also needs to
check for migration blockers. For example, this catches passed-through
PCI devices, where the driver does not support migration.
However, the commit notes:
> There is really no difference between live migration and savevm, except
> that savevm does not require bdrv_invalidate_cache to be implemented
> by all disks. However, it is unlikely that savevm is used with anything
> except qcow2 disks, so the penalty is small and worth the improvement
> in catching bad usage of savevm.
and for Proxmox VE, suspend-to-disk with VMDK does use savevm-async
and would be broken by simply using migration_is_blocked(). To keep
this working, introduce a new helper that filters blockers with the
prefix used by the VMDK migration blocker.
The function qemu_savevm_state_blocked() is called as part of
migration_is_blocked_allow_prefix() so no check is lost with this
patch.
Signed-off-by: Fiona Ebner <f.ebner at proxmox.com>
---
An alternative would be to mark the VMDK blocker as a
"live-migration-only" blocker and extending migration_is_blocked() or
using separate helpers to check for migration and snapshot blockers
differently. But that requires touching more machinery and probably
needs more adaptation going forward than the approach here.
migration/migration.c | 22 ++++++++++++++++++++++
migration/migration.h | 1 +
migration/savevm-async.c | 7 ++++++-
3 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/migration/migration.c b/migration/migration.c
index b8d7e471a4..6235309a00 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -1897,6 +1897,28 @@ void qmp_migrate_pause(Error **errp)
"during postcopy-active or postcopy-recover state");
}
+/*
+ * HACK to allow hibernation in Proxmox VE even when VMDK image is present.
+ */
+bool migration_is_blocked_allow_prefix(Error **errp, const char *prefix)
+{
+ GSList *blockers = migration_blockers[migrate_mode()];
+
+ if (qemu_savevm_state_blocked(errp)) {
+ return true;
+ }
+
+ while (blockers) {
+ if (!g_str_has_prefix(error_get_pretty(blockers->data), prefix)) {
+ error_propagate(errp, error_copy(blockers->data));
+ return true;
+ }
+ blockers = g_slist_next(blockers);
+ }
+
+ return false;
+}
+
bool migration_is_blocked(Error **errp)
{
GSList *blockers = migration_blockers[migrate_mode()];
diff --git a/migration/migration.h b/migration/migration.h
index 8045e39c26..575805a8e2 100644
--- a/migration/migration.h
+++ b/migration/migration.h
@@ -484,6 +484,7 @@ int migration_call_notifiers(MigrationState *s, MigrationEventType type,
Error **errp);
int migrate_init(MigrationState *s, Error **errp);
+bool migration_is_blocked_allow_prefix(Error **errp, const char *prefix);
bool migration_is_blocked(Error **errp);
/* True if outgoing migration has entered postcopy phase */
bool migration_in_postcopy(void);
diff --git a/migration/savevm-async.c b/migration/savevm-async.c
index bf36fc06d2..33085446e1 100644
--- a/migration/savevm-async.c
+++ b/migration/savevm-async.c
@@ -363,7 +363,12 @@ void qmp_savevm_start(const char *statefile, Error **errp)
return;
}
- if (qemu_savevm_state_blocked(errp)) {
+ /*
+ * The limitation for VMDK images only applies to live-migration, not
+ * snapshots, see commit 5aaac46793 ("migration: savevm: consult migration
+ * blockers").
+ */
+ if (migration_is_blocked_allow_prefix(errp, "The vmdk format used by node")) {
return;
}
--
2.39.2
More information about the pve-devel
mailing list