]> git.proxmox.com Git - pve-qemu.git/blob - debian/patches/pve/0035-PVE-Migrate-dirty-bitmap-state-via-savevm.patch
squash related patches
[pve-qemu.git] / debian / patches / pve / 0035-PVE-Migrate-dirty-bitmap-state-via-savevm.patch
1 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 From: Stefan Reiter <s.reiter@proxmox.com>
3 Date: Thu, 22 Oct 2020 17:34:18 +0200
4 Subject: [PATCH] PVE: Migrate dirty bitmap state via savevm
5
6 QEMU provides 'savevm' registrations as a mechanism for arbitrary state
7 to be migrated along with a VM. Use this to send a serialized version of
8 dirty bitmap state data from proxmox-backup-qemu, and restore it on the
9 target node.
10
11 Also add a flag to query-proxmox-support so qemu-server can determine if
12 safe migration is possible and makes sense.
13
14 Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
15 Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
16 [FE: split up state_pending for 8.0]
17 Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
18 ---
19 include/migration/misc.h | 3 ++
20 migration/meson.build | 2 +
21 migration/migration.c | 1 +
22 migration/pbs-state.c | 104 +++++++++++++++++++++++++++++++++++++++
23 pve-backup.c | 1 +
24 qapi/block-core.json | 6 +++
25 6 files changed, 117 insertions(+)
26 create mode 100644 migration/pbs-state.c
27
28 diff --git a/include/migration/misc.h b/include/migration/misc.h
29 index 8b49841016..78f63ca400 100644
30 --- a/include/migration/misc.h
31 +++ b/include/migration/misc.h
32 @@ -77,4 +77,7 @@ bool migration_in_bg_snapshot(void);
33 /* migration/block-dirty-bitmap.c */
34 void dirty_bitmap_mig_init(void);
35
36 +/* migration/pbs-state.c */
37 +void pbs_state_mig_init(void);
38 +
39 #endif
40 diff --git a/migration/meson.build b/migration/meson.build
41 index a7824b5266..de6a271b58 100644
42 --- a/migration/meson.build
43 +++ b/migration/meson.build
44 @@ -6,8 +6,10 @@ migration_files = files(
45 'vmstate.c',
46 'qemu-file.c',
47 'yank_functions.c',
48 + 'pbs-state.c',
49 )
50 softmmu_ss.add(migration_files)
51 +softmmu_ss.add(libproxmox_backup_qemu)
52
53 softmmu_ss.add(files(
54 'block-dirty-bitmap.c',
55 diff --git a/migration/migration.c b/migration/migration.c
56 index bda4789193..c8318aa258 100644
57 --- a/migration/migration.c
58 +++ b/migration/migration.c
59 @@ -245,6 +245,7 @@ void migration_object_init(void)
60 blk_mig_init();
61 ram_mig_init();
62 dirty_bitmap_mig_init();
63 + pbs_state_mig_init();
64 }
65
66 void migration_cancel(const Error *error)
67 diff --git a/migration/pbs-state.c b/migration/pbs-state.c
68 new file mode 100644
69 index 0000000000..887e998b9e
70 --- /dev/null
71 +++ b/migration/pbs-state.c
72 @@ -0,0 +1,104 @@
73 +/*
74 + * PBS (dirty-bitmap) state migration
75 + */
76 +
77 +#include "qemu/osdep.h"
78 +#include "migration/misc.h"
79 +#include "qemu-file.h"
80 +#include "migration/vmstate.h"
81 +#include "migration/register.h"
82 +#include "proxmox-backup-qemu.h"
83 +
84 +typedef struct PBSState {
85 + bool active;
86 +} PBSState;
87 +
88 +/* state is accessed via this static variable directly, 'opaque' is NULL */
89 +static PBSState pbs_state;
90 +
91 +static void pbs_state_pending(void *opaque, uint64_t *must_precopy,
92 + uint64_t *can_postcopy)
93 +{
94 + /* we send everything in save_setup, so nothing is ever pending */
95 +}
96 +
97 +/* receive PBS state via f and deserialize, called on target */
98 +static int pbs_state_load(QEMUFile *f, void *opaque, int version_id)
99 +{
100 + /* safe cast, we cannot migrate to target with less bits than source */
101 + size_t buf_size = (size_t)qemu_get_be64(f);
102 +
103 + uint8_t *buf = (uint8_t *)malloc(buf_size);
104 + size_t read = qemu_get_buffer(f, buf, buf_size);
105 +
106 + if (read < buf_size) {
107 + fprintf(stderr, "error receiving PBS state: not enough data\n");
108 + return -EIO;
109 + }
110 +
111 + proxmox_import_state(buf, buf_size);
112 +
113 + free(buf);
114 + return 0;
115 +}
116 +
117 +/* serialize PBS state and send to target via f, called on source */
118 +static int pbs_state_save_setup(QEMUFile *f, void *opaque)
119 +{
120 + size_t buf_size;
121 + uint8_t *buf = proxmox_export_state(&buf_size);
122 +
123 + /* LV encoding */
124 + qemu_put_be64(f, buf_size);
125 + qemu_put_buffer(f, buf, buf_size);
126 +
127 + proxmox_free_state_buf(buf);
128 + pbs_state.active = false;
129 + return 0;
130 +}
131 +
132 +static bool pbs_state_is_active(void *opaque)
133 +{
134 + /* we need to return active exactly once, else .save_setup is never called,
135 + * but if we'd just return true the migration doesn't make progress since
136 + * it'd be waiting for us */
137 + return pbs_state.active;
138 +}
139 +
140 +static bool pbs_state_is_active_iterate(void *opaque)
141 +{
142 + /* we don't iterate, everything is sent in save_setup */
143 + return pbs_state_is_active(opaque);
144 +}
145 +
146 +static bool pbs_state_has_postcopy(void *opaque)
147 +{
148 + /* PBS state can't change during a migration (since that's blocking any
149 + * potential backups), so we can copy everything before the VM is stopped */
150 + return false;
151 +}
152 +
153 +static void pbs_state_save_cleanup(void *opaque)
154 +{
155 + /* reset active after migration succeeds or fails */
156 + pbs_state.active = false;
157 +}
158 +
159 +static SaveVMHandlers savevm_pbs_state_handlers = {
160 + .save_setup = pbs_state_save_setup,
161 + .has_postcopy = pbs_state_has_postcopy,
162 + .state_pending_exact = pbs_state_pending,
163 + .state_pending_estimate = pbs_state_pending,
164 + .is_active_iterate = pbs_state_is_active_iterate,
165 + .load_state = pbs_state_load,
166 + .is_active = pbs_state_is_active,
167 + .save_cleanup = pbs_state_save_cleanup,
168 +};
169 +
170 +void pbs_state_mig_init(void)
171 +{
172 + pbs_state.active = true;
173 + register_savevm_live("pbs-state", 0, 1,
174 + &savevm_pbs_state_handlers,
175 + NULL);
176 +}
177 diff --git a/pve-backup.c b/pve-backup.c
178 index dd72ee0ed6..cb5312fff3 100644
179 --- a/pve-backup.c
180 +++ b/pve-backup.c
181 @@ -1090,6 +1090,7 @@ ProxmoxSupportStatus *qmp_query_proxmox_support(Error **errp)
182 ret->pbs_library_version = g_strdup(proxmox_backup_qemu_version());
183 ret->pbs_dirty_bitmap = true;
184 ret->pbs_dirty_bitmap_savevm = true;
185 + ret->pbs_dirty_bitmap_migration = true;
186 ret->query_bitmap_info = true;
187 ret->pbs_masterkey = true;
188 ret->backup_max_workers = true;
189 diff --git a/qapi/block-core.json b/qapi/block-core.json
190 index 47118bf83e..809f3c61bc 100644
191 --- a/qapi/block-core.json
192 +++ b/qapi/block-core.json
193 @@ -984,6 +984,11 @@
194 # @pbs-dirty-bitmap-savevm: True if 'dirty-bitmaps' migration capability can
195 # safely be set for savevm-async.
196 #
197 +# @pbs-dirty-bitmap-migration: True if safe migration of dirty-bitmaps including
198 +# PBS state is supported. Enabling 'dirty-bitmaps'
199 +# migration cap if this is false/unset may lead
200 +# to crashes on migration!
201 +#
202 # @pbs-masterkey: True if the QMP backup call supports the 'master_keyfile'
203 # parameter.
204 #
205 @@ -994,6 +999,7 @@
206 'data': { 'pbs-dirty-bitmap': 'bool',
207 'query-bitmap-info': 'bool',
208 'pbs-dirty-bitmap-savevm': 'bool',
209 + 'pbs-dirty-bitmap-migration': 'bool',
210 'pbs-masterkey': 'bool',
211 'pbs-library-version': 'str',
212 'backup-max-workers': 'bool' } }