]> git.proxmox.com Git - pve-qemu.git/blob - debian/patches/pve/0034-PVE-Migrate-dirty-bitmap-state-via-savevm.patch
backup: improve error when copy-before-write fails for fleecing
[pve-qemu.git] / debian / patches / pve / 0034-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 7dcc0b5c2c..4c940b2475 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 07f6057acc..343994d891 100644
42 --- a/migration/meson.build
43 +++ b/migration/meson.build
44 @@ -7,7 +7,9 @@ migration_files = files(
45 'vmstate.c',
46 'qemu-file.c',
47 'yank_functions.c',
48 + 'pbs-state.c',
49 )
50 +system_ss.add(libproxmox_backup_qemu)
51
52 system_ss.add(files(
53 'block-dirty-bitmap.c',
54 diff --git a/migration/migration.c b/migration/migration.c
55 index 7a4c8beb5d..0a955a2a18 100644
56 --- a/migration/migration.c
57 +++ b/migration/migration.c
58 @@ -162,6 +162,7 @@ void migration_object_init(void)
59 blk_mig_init();
60 ram_mig_init();
61 dirty_bitmap_mig_init();
62 + pbs_state_mig_init();
63 }
64
65 void migration_cancel(const Error *error)
66 diff --git a/migration/pbs-state.c b/migration/pbs-state.c
67 new file mode 100644
68 index 0000000000..887e998b9e
69 --- /dev/null
70 +++ b/migration/pbs-state.c
71 @@ -0,0 +1,104 @@
72 +/*
73 + * PBS (dirty-bitmap) state migration
74 + */
75 +
76 +#include "qemu/osdep.h"
77 +#include "migration/misc.h"
78 +#include "qemu-file.h"
79 +#include "migration/vmstate.h"
80 +#include "migration/register.h"
81 +#include "proxmox-backup-qemu.h"
82 +
83 +typedef struct PBSState {
84 + bool active;
85 +} PBSState;
86 +
87 +/* state is accessed via this static variable directly, 'opaque' is NULL */
88 +static PBSState pbs_state;
89 +
90 +static void pbs_state_pending(void *opaque, uint64_t *must_precopy,
91 + uint64_t *can_postcopy)
92 +{
93 + /* we send everything in save_setup, so nothing is ever pending */
94 +}
95 +
96 +/* receive PBS state via f and deserialize, called on target */
97 +static int pbs_state_load(QEMUFile *f, void *opaque, int version_id)
98 +{
99 + /* safe cast, we cannot migrate to target with less bits than source */
100 + size_t buf_size = (size_t)qemu_get_be64(f);
101 +
102 + uint8_t *buf = (uint8_t *)malloc(buf_size);
103 + size_t read = qemu_get_buffer(f, buf, buf_size);
104 +
105 + if (read < buf_size) {
106 + fprintf(stderr, "error receiving PBS state: not enough data\n");
107 + return -EIO;
108 + }
109 +
110 + proxmox_import_state(buf, buf_size);
111 +
112 + free(buf);
113 + return 0;
114 +}
115 +
116 +/* serialize PBS state and send to target via f, called on source */
117 +static int pbs_state_save_setup(QEMUFile *f, void *opaque)
118 +{
119 + size_t buf_size;
120 + uint8_t *buf = proxmox_export_state(&buf_size);
121 +
122 + /* LV encoding */
123 + qemu_put_be64(f, buf_size);
124 + qemu_put_buffer(f, buf, buf_size);
125 +
126 + proxmox_free_state_buf(buf);
127 + pbs_state.active = false;
128 + return 0;
129 +}
130 +
131 +static bool pbs_state_is_active(void *opaque)
132 +{
133 + /* we need to return active exactly once, else .save_setup is never called,
134 + * but if we'd just return true the migration doesn't make progress since
135 + * it'd be waiting for us */
136 + return pbs_state.active;
137 +}
138 +
139 +static bool pbs_state_is_active_iterate(void *opaque)
140 +{
141 + /* we don't iterate, everything is sent in save_setup */
142 + return pbs_state_is_active(opaque);
143 +}
144 +
145 +static bool pbs_state_has_postcopy(void *opaque)
146 +{
147 + /* PBS state can't change during a migration (since that's blocking any
148 + * potential backups), so we can copy everything before the VM is stopped */
149 + return false;
150 +}
151 +
152 +static void pbs_state_save_cleanup(void *opaque)
153 +{
154 + /* reset active after migration succeeds or fails */
155 + pbs_state.active = false;
156 +}
157 +
158 +static SaveVMHandlers savevm_pbs_state_handlers = {
159 + .save_setup = pbs_state_save_setup,
160 + .has_postcopy = pbs_state_has_postcopy,
161 + .state_pending_exact = pbs_state_pending,
162 + .state_pending_estimate = pbs_state_pending,
163 + .is_active_iterate = pbs_state_is_active_iterate,
164 + .load_state = pbs_state_load,
165 + .is_active = pbs_state_is_active,
166 + .save_cleanup = pbs_state_save_cleanup,
167 +};
168 +
169 +void pbs_state_mig_init(void)
170 +{
171 + pbs_state.active = true;
172 + register_savevm_live("pbs-state", 0, 1,
173 + &savevm_pbs_state_handlers,
174 + NULL);
175 +}
176 diff --git a/pve-backup.c b/pve-backup.c
177 index ae3d137e12..e6b17b797e 100644
178 --- a/pve-backup.c
179 +++ b/pve-backup.c
180 @@ -1082,6 +1082,7 @@ ProxmoxSupportStatus *qmp_query_proxmox_support(Error **errp)
181 ret->pbs_library_version = g_strdup(proxmox_backup_qemu_version());
182 ret->pbs_dirty_bitmap = true;
183 ret->pbs_dirty_bitmap_savevm = true;
184 + ret->pbs_dirty_bitmap_migration = true;
185 ret->query_bitmap_info = true;
186 ret->pbs_masterkey = true;
187 ret->backup_max_workers = true;
188 diff --git a/qapi/block-core.json b/qapi/block-core.json
189 index d67a6d448a..09de550c95 100644
190 --- a/qapi/block-core.json
191 +++ b/qapi/block-core.json
192 @@ -991,6 +991,11 @@
193 # @pbs-dirty-bitmap-savevm: True if 'dirty-bitmaps' migration capability can
194 # safely be set for savevm-async.
195 #
196 +# @pbs-dirty-bitmap-migration: True if safe migration of dirty-bitmaps including
197 +# PBS state is supported. Enabling 'dirty-bitmaps'
198 +# migration cap if this is false/unset may lead
199 +# to crashes on migration!
200 +#
201 # @pbs-masterkey: True if the QMP backup call supports the 'master_keyfile'
202 # parameter.
203 #
204 @@ -1001,6 +1006,7 @@
205 'data': { 'pbs-dirty-bitmap': 'bool',
206 'query-bitmap-info': 'bool',
207 'pbs-dirty-bitmap-savevm': 'bool',
208 + 'pbs-dirty-bitmap-migration': 'bool',
209 'pbs-masterkey': 'bool',
210 'pbs-library-version': 'str',
211 'backup-max-workers': 'bool' } }