mirror of
https://git.proxmox.com/git/pve-qemu
synced 2025-08-17 01:38:46 +00:00

Many stable fixes came in since the last bump, a few of which were actually already present. Notable ones not yet present include a few guest-triggerable assert fixes, some AHCI/IDE fixes (including the fix for bug #2784), TGC fixes for i386 and ARM, VirtIO fixes, fix to avoid VNC clipboard denial-of-service. The reentrancy patches that landed upstream/stable were a newer version than the ones backported initially here, so it was necessary to explicitly drop them before rebase (which then picked up the upstream version). There were no other conflicts. Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
213 lines
6.7 KiB
Diff
213 lines
6.7 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Stefan Reiter <s.reiter@proxmox.com>
|
|
Date: Thu, 22 Oct 2020 17:34:18 +0200
|
|
Subject: [PATCH] PVE: Migrate dirty bitmap state via savevm
|
|
|
|
QEMU provides 'savevm' registrations as a mechanism for arbitrary state
|
|
to be migrated along with a VM. Use this to send a serialized version of
|
|
dirty bitmap state data from proxmox-backup-qemu, and restore it on the
|
|
target node.
|
|
|
|
Also add a flag to query-proxmox-support so qemu-server can determine if
|
|
safe migration is possible and makes sense.
|
|
|
|
Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
|
|
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
|
|
---
|
|
include/migration/misc.h | 3 ++
|
|
migration/meson.build | 2 +
|
|
migration/migration.c | 1 +
|
|
migration/pbs-state.c | 106 +++++++++++++++++++++++++++++++++++++++
|
|
pve-backup.c | 1 +
|
|
qapi/block-core.json | 6 +++
|
|
6 files changed, 119 insertions(+)
|
|
create mode 100644 migration/pbs-state.c
|
|
|
|
diff --git a/include/migration/misc.h b/include/migration/misc.h
|
|
index 465906710d..4f0aeceb6f 100644
|
|
--- a/include/migration/misc.h
|
|
+++ b/include/migration/misc.h
|
|
@@ -75,4 +75,7 @@ bool migration_in_bg_snapshot(void);
|
|
/* migration/block-dirty-bitmap.c */
|
|
void dirty_bitmap_mig_init(void);
|
|
|
|
+/* migration/pbs-state.c */
|
|
+void pbs_state_mig_init(void);
|
|
+
|
|
#endif
|
|
diff --git a/migration/meson.build b/migration/meson.build
|
|
index 0842d00cd2..d012f4d8d3 100644
|
|
--- a/migration/meson.build
|
|
+++ b/migration/meson.build
|
|
@@ -6,8 +6,10 @@ migration_files = files(
|
|
'vmstate.c',
|
|
'qemu-file.c',
|
|
'yank_functions.c',
|
|
+ 'pbs-state.c',
|
|
)
|
|
softmmu_ss.add(migration_files)
|
|
+softmmu_ss.add(libproxmox_backup_qemu)
|
|
|
|
softmmu_ss.add(files(
|
|
'block-dirty-bitmap.c',
|
|
diff --git a/migration/migration.c b/migration/migration.c
|
|
index 9b496cce1d..421b4ee225 100644
|
|
--- a/migration/migration.c
|
|
+++ b/migration/migration.c
|
|
@@ -229,6 +229,7 @@ void migration_object_init(void)
|
|
blk_mig_init();
|
|
ram_mig_init();
|
|
dirty_bitmap_mig_init();
|
|
+ pbs_state_mig_init();
|
|
}
|
|
|
|
void migration_cancel(const Error *error)
|
|
diff --git a/migration/pbs-state.c b/migration/pbs-state.c
|
|
new file mode 100644
|
|
index 0000000000..29f2b3860d
|
|
--- /dev/null
|
|
+++ b/migration/pbs-state.c
|
|
@@ -0,0 +1,106 @@
|
|
+/*
|
|
+ * PBS (dirty-bitmap) state migration
|
|
+ */
|
|
+
|
|
+#include "qemu/osdep.h"
|
|
+#include "migration/misc.h"
|
|
+#include "qemu-file.h"
|
|
+#include "migration/vmstate.h"
|
|
+#include "migration/register.h"
|
|
+#include "proxmox-backup-qemu.h"
|
|
+
|
|
+typedef struct PBSState {
|
|
+ bool active;
|
|
+} PBSState;
|
|
+
|
|
+/* state is accessed via this static variable directly, 'opaque' is NULL */
|
|
+static PBSState pbs_state;
|
|
+
|
|
+static void pbs_state_save_pending(QEMUFile *f, void *opaque,
|
|
+ uint64_t max_size,
|
|
+ uint64_t *res_precopy_only,
|
|
+ uint64_t *res_compatible,
|
|
+ uint64_t *res_postcopy_only)
|
|
+{
|
|
+ /* we send everything in save_setup, so nothing is ever pending */
|
|
+}
|
|
+
|
|
+/* receive PBS state via f and deserialize, called on target */
|
|
+static int pbs_state_load(QEMUFile *f, void *opaque, int version_id)
|
|
+{
|
|
+ /* safe cast, we cannot migrate to target with less bits than source */
|
|
+ size_t buf_size = (size_t)qemu_get_be64(f);
|
|
+
|
|
+ uint8_t *buf = (uint8_t *)malloc(buf_size);
|
|
+ size_t read = qemu_get_buffer(f, buf, buf_size);
|
|
+
|
|
+ if (read < buf_size) {
|
|
+ fprintf(stderr, "error receiving PBS state: not enough data\n");
|
|
+ return -EIO;
|
|
+ }
|
|
+
|
|
+ proxmox_import_state(buf, buf_size);
|
|
+
|
|
+ free(buf);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/* serialize PBS state and send to target via f, called on source */
|
|
+static int pbs_state_save_setup(QEMUFile *f, void *opaque)
|
|
+{
|
|
+ size_t buf_size;
|
|
+ uint8_t *buf = proxmox_export_state(&buf_size);
|
|
+
|
|
+ /* LV encoding */
|
|
+ qemu_put_be64(f, buf_size);
|
|
+ qemu_put_buffer(f, buf, buf_size);
|
|
+
|
|
+ proxmox_free_state_buf(buf);
|
|
+ pbs_state.active = false;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static bool pbs_state_is_active(void *opaque)
|
|
+{
|
|
+ /* we need to return active exactly once, else .save_setup is never called,
|
|
+ * but if we'd just return true the migration doesn't make progress since
|
|
+ * it'd be waiting for us */
|
|
+ return pbs_state.active;
|
|
+}
|
|
+
|
|
+static bool pbs_state_is_active_iterate(void *opaque)
|
|
+{
|
|
+ /* we don't iterate, everything is sent in save_setup */
|
|
+ return pbs_state_is_active(opaque);
|
|
+}
|
|
+
|
|
+static bool pbs_state_has_postcopy(void *opaque)
|
|
+{
|
|
+ /* PBS state can't change during a migration (since that's blocking any
|
|
+ * potential backups), so we can copy everything before the VM is stopped */
|
|
+ return false;
|
|
+}
|
|
+
|
|
+static void pbs_state_save_cleanup(void *opaque)
|
|
+{
|
|
+ /* reset active after migration succeeds or fails */
|
|
+ pbs_state.active = false;
|
|
+}
|
|
+
|
|
+static SaveVMHandlers savevm_pbs_state_handlers = {
|
|
+ .save_setup = pbs_state_save_setup,
|
|
+ .has_postcopy = pbs_state_has_postcopy,
|
|
+ .save_live_pending = pbs_state_save_pending,
|
|
+ .is_active_iterate = pbs_state_is_active_iterate,
|
|
+ .load_state = pbs_state_load,
|
|
+ .is_active = pbs_state_is_active,
|
|
+ .save_cleanup = pbs_state_save_cleanup,
|
|
+};
|
|
+
|
|
+void pbs_state_mig_init(void)
|
|
+{
|
|
+ pbs_state.active = true;
|
|
+ register_savevm_live("pbs-state", 0, 1,
|
|
+ &savevm_pbs_state_handlers,
|
|
+ NULL);
|
|
+}
|
|
diff --git a/pve-backup.c b/pve-backup.c
|
|
index 7bd9d06346..5662f48b72 100644
|
|
--- a/pve-backup.c
|
|
+++ b/pve-backup.c
|
|
@@ -1128,6 +1128,7 @@ ProxmoxSupportStatus *qmp_query_proxmox_support(Error **errp)
|
|
ret->pbs_library_version = g_strdup(proxmox_backup_qemu_version());
|
|
ret->pbs_dirty_bitmap = true;
|
|
ret->pbs_dirty_bitmap_savevm = true;
|
|
+ ret->pbs_dirty_bitmap_migration = true;
|
|
ret->query_bitmap_info = true;
|
|
return ret;
|
|
}
|
|
diff --git a/qapi/block-core.json b/qapi/block-core.json
|
|
index bf559c6d52..24f30260c8 100644
|
|
--- a/qapi/block-core.json
|
|
+++ b/qapi/block-core.json
|
|
@@ -879,6 +879,11 @@
|
|
# @pbs-dirty-bitmap-savevm: True if 'dirty-bitmaps' migration capability can
|
|
# safely be set for savevm-async.
|
|
#
|
|
+# @pbs-dirty-bitmap-migration: True if safe migration of dirty-bitmaps including
|
|
+# PBS state is supported. Enabling 'dirty-bitmaps'
|
|
+# migration cap if this is false/unset may lead
|
|
+# to crashes on migration!
|
|
+#
|
|
# @pbs-library-version: Running version of libproxmox-backup-qemu0 library.
|
|
#
|
|
##
|
|
@@ -886,6 +891,7 @@
|
|
'data': { 'pbs-dirty-bitmap': 'bool',
|
|
'query-bitmap-info': 'bool',
|
|
'pbs-dirty-bitmap-savevm': 'bool',
|
|
+ 'pbs-dirty-bitmap-migration': 'bool',
|
|
'pbs-library-version': 'str' } }
|
|
|
|
##
|