db5d2a4b77
where there is no good reason to keep them separate. It's a pain during rebase if there are multiple patches changing the same code over and over again. This was especially bad for the backup-related patches. If the history of patches really is needed, it can be extracted via git. Additionally, compilation with partial application of patches was broken since a long time, because one of the master key changes became part of an earlier patch during a past rebase. If only the same files were changed by a subsequent patch and the changes felt to belong together (obvious for later bug fixes, but also done for features e.g. adding master key support for PBS), the patches were squashed together. The PBS namespace support patch was split into the individual parts it changes, i.e. PBS block driver, pbs-restore binary and QMP backup infrastructure, and squashed into the respective patches. No code change is intended, git diff in the submodule should not show any difference between applying all patches before this commit and applying all patches after this commit. The query-proxmox-support QMP function has been left as part of the "PVE-Backup: Proxmox backup patches for QEMU" patch, because it's currently only used there. If it ever is used elsewhere too, it can be split out from there. The recent alloc-track and BQL-related savevm-async changes have been left separate for now, because it's not 100% clear they are the best approach yet. This depends on what upstream decides about the BQL stuff and whether and what kind of issues with the changes pop up. The qemu-img dd snapshot patch has been re-ordered to after the other qemu-img dd patches. Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
213 lines
6.8 KiB
Diff
213 lines
6.8 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>
|
|
[FE: split up state_pending for 8.0]
|
|
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
|
|
---
|
|
include/migration/misc.h | 3 ++
|
|
migration/meson.build | 2 +
|
|
migration/migration.c | 1 +
|
|
migration/pbs-state.c | 104 +++++++++++++++++++++++++++++++++++++++
|
|
pve-backup.c | 1 +
|
|
qapi/block-core.json | 6 +++
|
|
6 files changed, 117 insertions(+)
|
|
create mode 100644 migration/pbs-state.c
|
|
|
|
diff --git a/include/migration/misc.h b/include/migration/misc.h
|
|
index 8b49841016..78f63ca400 100644
|
|
--- a/include/migration/misc.h
|
|
+++ b/include/migration/misc.h
|
|
@@ -77,4 +77,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 a7824b5266..de6a271b58 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 bda4789193..c8318aa258 100644
|
|
--- a/migration/migration.c
|
|
+++ b/migration/migration.c
|
|
@@ -245,6 +245,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..887e998b9e
|
|
--- /dev/null
|
|
+++ b/migration/pbs-state.c
|
|
@@ -0,0 +1,104 @@
|
|
+/*
|
|
+ * 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_pending(void *opaque, uint64_t *must_precopy,
|
|
+ uint64_t *can_postcopy)
|
|
+{
|
|
+ /* 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,
|
|
+ .state_pending_exact = pbs_state_pending,
|
|
+ .state_pending_estimate = pbs_state_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 dd72ee0ed6..cb5312fff3 100644
|
|
--- a/pve-backup.c
|
|
+++ b/pve-backup.c
|
|
@@ -1090,6 +1090,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;
|
|
ret->pbs_masterkey = true;
|
|
ret->backup_max_workers = true;
|
|
diff --git a/qapi/block-core.json b/qapi/block-core.json
|
|
index 47118bf83e..809f3c61bc 100644
|
|
--- a/qapi/block-core.json
|
|
+++ b/qapi/block-core.json
|
|
@@ -984,6 +984,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-masterkey: True if the QMP backup call supports the 'master_keyfile'
|
|
# parameter.
|
|
#
|
|
@@ -994,6 +999,7 @@
|
|
'data': { 'pbs-dirty-bitmap': 'bool',
|
|
'query-bitmap-info': 'bool',
|
|
'pbs-dirty-bitmap-savevm': 'bool',
|
|
+ 'pbs-dirty-bitmap-migration': 'bool',
|
|
'pbs-masterkey': 'bool',
|
|
'pbs-library-version': 'str',
|
|
'backup-max-workers': 'bool' } }
|