]> git.proxmox.com Git - mirror_qemu.git/blame - migration/options.c
migration: Create migrate_checkpoint_delay()
[mirror_qemu.git] / migration / options.c
CommitLineData
1f0776f1
JQ
1/*
2 * QEMU migration capabilities
3 *
4 * Copyright (c) 2012-2023 Red Hat Inc
5 *
6 * Authors:
7 * Orit Wasserman <owasserm@redhat.com>
8 * Juan Quintela <quintela@redhat.com>
9 *
10 * This work is licensed under the terms of the GNU GPL, version 2 or later.
11 * See the COPYING file in the top-level directory.
12 */
13
14#include "qemu/osdep.h"
77608706 15#include "qapi/error.h"
4d0c6b69 16#include "qapi/qapi-commands-migration.h"
f80196b7 17#include "qapi/qmp/qerror.h"
77608706 18#include "sysemu/runstate.h"
1f0776f1 19#include "migration.h"
77608706 20#include "ram.h"
1f0776f1
JQ
21#include "options.h"
22
23bool migrate_auto_converge(void)
24{
25 MigrationState *s;
26
27 s = migrate_get_current();
28
29 return s->capabilities[MIGRATION_CAPABILITY_AUTO_CONVERGE];
30}
31
32bool migrate_background_snapshot(void)
33{
34 MigrationState *s;
35
36 s = migrate_get_current();
37
38 return s->capabilities[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT];
39}
40
9d4b1e5f
JQ
41bool migrate_block(void)
42{
43 MigrationState *s;
44
45 s = migrate_get_current();
46
47 return s->capabilities[MIGRATION_CAPABILITY_BLOCK];
48}
49
5e804644
JQ
50bool migrate_colo(void)
51{
52 MigrationState *s = migrate_get_current();
53 return s->capabilities[MIGRATION_CAPABILITY_X_COLO];
54}
55
a7a94d14
JQ
56bool migrate_compress(void)
57{
58 MigrationState *s;
59
60 s = migrate_get_current();
61
62 return s->capabilities[MIGRATION_CAPABILITY_COMPRESS];
63}
64
1f0776f1
JQ
65bool migrate_dirty_bitmaps(void)
66{
67 MigrationState *s;
68
69 s = migrate_get_current();
70
71 return s->capabilities[MIGRATION_CAPABILITY_DIRTY_BITMAPS];
72}
73
b890902c
JQ
74bool migrate_events(void)
75{
76 MigrationState *s;
77
78 s = migrate_get_current();
79
80 return s->capabilities[MIGRATION_CAPABILITY_EVENTS];
81}
82
1f0776f1
JQ
83bool migrate_ignore_shared(void)
84{
85 MigrationState *s;
86
87 s = migrate_get_current();
88
89 return s->capabilities[MIGRATION_CAPABILITY_X_IGNORE_SHARED];
90}
91
92bool migrate_late_block_activate(void)
93{
94 MigrationState *s;
95
96 s = migrate_get_current();
97
98 return s->capabilities[MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE];
99}
100
51b07548
JQ
101bool migrate_multifd(void)
102{
103 MigrationState *s;
104
105 s = migrate_get_current();
106
107 return s->capabilities[MIGRATION_CAPABILITY_MULTIFD];
108}
109
1f0776f1
JQ
110bool migrate_pause_before_switchover(void)
111{
112 MigrationState *s;
113
114 s = migrate_get_current();
115
116 return s->capabilities[MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER];
117}
118
119bool migrate_postcopy_blocktime(void)
120{
121 MigrationState *s;
122
123 s = migrate_get_current();
124
125 return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME];
126}
127
128bool migrate_postcopy_preempt(void)
129{
130 MigrationState *s;
131
132 s = migrate_get_current();
133
134 return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT];
135}
136
137bool migrate_postcopy_ram(void)
138{
139 MigrationState *s;
140
141 s = migrate_get_current();
142
143 return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_RAM];
144}
145
17cba690
JQ
146bool migrate_rdma_pin_all(void)
147{
148 MigrationState *s = migrate_get_current();
149
150 return s->capabilities[MIGRATION_CAPABILITY_RDMA_PIN_ALL];
151}
152
1f0776f1
JQ
153bool migrate_release_ram(void)
154{
155 MigrationState *s;
156
157 s = migrate_get_current();
158
159 return s->capabilities[MIGRATION_CAPABILITY_RELEASE_RAM];
160}
161
38ad1110
JQ
162bool migrate_return_path(void)
163{
164 MigrationState *s;
165
166 s = migrate_get_current();
167
168 return s->capabilities[MIGRATION_CAPABILITY_RETURN_PATH];
169}
170
1f0776f1
JQ
171bool migrate_validate_uuid(void)
172{
173 MigrationState *s;
174
175 s = migrate_get_current();
176
177 return s->capabilities[MIGRATION_CAPABILITY_VALIDATE_UUID];
178}
179
87dca0c9
JQ
180bool migrate_xbzrle(void)
181{
182 MigrationState *s;
183
184 s = migrate_get_current();
185
186 return s->capabilities[MIGRATION_CAPABILITY_XBZRLE];
187}
188
1f0776f1
JQ
189bool migrate_zero_blocks(void)
190{
191 MigrationState *s;
192
193 s = migrate_get_current();
194
195 return s->capabilities[MIGRATION_CAPABILITY_ZERO_BLOCKS];
196}
b4bc342c
JQ
197
198bool migrate_zero_copy_send(void)
199{
200 MigrationState *s;
201
202 s = migrate_get_current();
203
204 return s->capabilities[MIGRATION_CAPABILITY_ZERO_COPY_SEND];
205}
77608706
JQ
206typedef enum WriteTrackingSupport {
207 WT_SUPPORT_UNKNOWN = 0,
208 WT_SUPPORT_ABSENT,
209 WT_SUPPORT_AVAILABLE,
210 WT_SUPPORT_COMPATIBLE
211} WriteTrackingSupport;
212
213static
214WriteTrackingSupport migrate_query_write_tracking(void)
215{
216 /* Check if kernel supports required UFFD features */
217 if (!ram_write_tracking_available()) {
218 return WT_SUPPORT_ABSENT;
219 }
220 /*
221 * Check if current memory configuration is
222 * compatible with required UFFD features.
223 */
224 if (!ram_write_tracking_compatible()) {
225 return WT_SUPPORT_AVAILABLE;
226 }
227
228 return WT_SUPPORT_COMPATIBLE;
229}
230
231/* Migration capabilities set */
232struct MigrateCapsSet {
233 int size; /* Capability set size */
234 MigrationCapability caps[]; /* Variadic array of capabilities */
235};
236typedef struct MigrateCapsSet MigrateCapsSet;
237
238/* Define and initialize MigrateCapsSet */
239#define INITIALIZE_MIGRATE_CAPS_SET(_name, ...) \
240 MigrateCapsSet _name = { \
241 .size = sizeof((int []) { __VA_ARGS__ }) / sizeof(int), \
242 .caps = { __VA_ARGS__ } \
243 }
244
245/* Background-snapshot compatibility check list */
246static const
247INITIALIZE_MIGRATE_CAPS_SET(check_caps_background_snapshot,
248 MIGRATION_CAPABILITY_POSTCOPY_RAM,
249 MIGRATION_CAPABILITY_DIRTY_BITMAPS,
250 MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME,
251 MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE,
252 MIGRATION_CAPABILITY_RETURN_PATH,
253 MIGRATION_CAPABILITY_MULTIFD,
254 MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER,
255 MIGRATION_CAPABILITY_AUTO_CONVERGE,
256 MIGRATION_CAPABILITY_RELEASE_RAM,
257 MIGRATION_CAPABILITY_RDMA_PIN_ALL,
258 MIGRATION_CAPABILITY_COMPRESS,
259 MIGRATION_CAPABILITY_XBZRLE,
260 MIGRATION_CAPABILITY_X_COLO,
261 MIGRATION_CAPABILITY_VALIDATE_UUID,
262 MIGRATION_CAPABILITY_ZERO_COPY_SEND);
263
264/**
265 * @migration_caps_check - check capability compatibility
266 *
267 * @old_caps: old capability list
268 * @new_caps: new capability list
269 * @errp: set *errp if the check failed, with reason
270 *
271 * Returns true if check passed, otherwise false.
272 */
273bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp)
274{
275 MigrationIncomingState *mis = migration_incoming_get_current();
276
277#ifndef CONFIG_LIVE_BLOCK_MIGRATION
278 if (new_caps[MIGRATION_CAPABILITY_BLOCK]) {
279 error_setg(errp, "QEMU compiled without old-style (blk/-b, inc/-i) "
280 "block migration");
281 error_append_hint(errp, "Use drive_mirror+NBD instead.\n");
282 return false;
283 }
284#endif
285
286#ifndef CONFIG_REPLICATION
287 if (new_caps[MIGRATION_CAPABILITY_X_COLO]) {
288 error_setg(errp, "QEMU compiled without replication module"
289 " can't enable COLO");
290 error_append_hint(errp, "Please enable replication before COLO.\n");
291 return false;
292 }
293#endif
294
295 if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) {
296 /* This check is reasonably expensive, so only when it's being
297 * set the first time, also it's only the destination that needs
298 * special support.
299 */
300 if (!old_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM] &&
301 runstate_check(RUN_STATE_INMIGRATE) &&
302 !postcopy_ram_supported_by_host(mis)) {
303 /* postcopy_ram_supported_by_host will have emitted a more
304 * detailed message
305 */
306 error_setg(errp, "Postcopy is not supported");
307 return false;
308 }
309
310 if (new_caps[MIGRATION_CAPABILITY_X_IGNORE_SHARED]) {
311 error_setg(errp, "Postcopy is not compatible with ignore-shared");
312 return false;
313 }
314 }
315
316 if (new_caps[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT]) {
317 WriteTrackingSupport wt_support;
318 int idx;
319 /*
320 * Check if 'background-snapshot' capability is supported by
321 * host kernel and compatible with guest memory configuration.
322 */
323 wt_support = migrate_query_write_tracking();
324 if (wt_support < WT_SUPPORT_AVAILABLE) {
325 error_setg(errp, "Background-snapshot is not supported by host kernel");
326 return false;
327 }
328 if (wt_support < WT_SUPPORT_COMPATIBLE) {
329 error_setg(errp, "Background-snapshot is not compatible "
330 "with guest memory configuration");
331 return false;
332 }
333
334 /*
335 * Check if there are any migration capabilities
336 * incompatible with 'background-snapshot'.
337 */
338 for (idx = 0; idx < check_caps_background_snapshot.size; idx++) {
339 int incomp_cap = check_caps_background_snapshot.caps[idx];
340 if (new_caps[incomp_cap]) {
341 error_setg(errp,
342 "Background-snapshot is not compatible with %s",
343 MigrationCapability_str(incomp_cap));
344 return false;
345 }
346 }
347 }
348
349#ifdef CONFIG_LINUX
350 if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND] &&
351 (!new_caps[MIGRATION_CAPABILITY_MULTIFD] ||
352 new_caps[MIGRATION_CAPABILITY_COMPRESS] ||
353 new_caps[MIGRATION_CAPABILITY_XBZRLE] ||
354 migrate_multifd_compression() ||
355 migrate_use_tls())) {
356 error_setg(errp,
357 "Zero copy only available for non-compressed non-TLS multifd migration");
358 return false;
359 }
360#else
361 if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND]) {
362 error_setg(errp,
363 "Zero copy currently only available on Linux");
364 return false;
365 }
366#endif
367
368 if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT]) {
369 if (!new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) {
370 error_setg(errp, "Postcopy preempt requires postcopy-ram");
371 return false;
372 }
373
374 /*
375 * Preempt mode requires urgent pages to be sent in separate
376 * channel, OTOH compression logic will disorder all pages into
377 * different compression channels, which is not compatible with the
378 * preempt assumptions on channel assignments.
379 */
380 if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) {
381 error_setg(errp, "Postcopy preempt not compatible with compress");
382 return false;
383 }
384 }
385
386 if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) {
387 if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) {
388 error_setg(errp, "Multifd is not compatible with compress");
389 return false;
390 }
391 }
392
393 return true;
394}
4d0c6b69 395
f80196b7
JQ
396bool migrate_cap_set(int cap, bool value, Error **errp)
397{
398 MigrationState *s = migrate_get_current();
399 bool new_caps[MIGRATION_CAPABILITY__MAX];
400
401 if (migration_is_running(s->state)) {
402 error_setg(errp, QERR_MIGRATION_ACTIVE);
403 return false;
404 }
405
406 memcpy(new_caps, s->capabilities, sizeof(new_caps));
407 new_caps[cap] = value;
408
409 if (!migrate_caps_check(s->capabilities, new_caps, errp)) {
410 return false;
411 }
412 s->capabilities[cap] = value;
413 return true;
414}
415
4d0c6b69
JQ
416MigrationCapabilityStatusList *qmp_query_migrate_capabilities(Error **errp)
417{
418 MigrationCapabilityStatusList *head = NULL, **tail = &head;
419 MigrationCapabilityStatus *caps;
420 MigrationState *s = migrate_get_current();
421 int i;
422
423 for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
424#ifndef CONFIG_LIVE_BLOCK_MIGRATION
425 if (i == MIGRATION_CAPABILITY_BLOCK) {
426 continue;
427 }
428#endif
429 caps = g_malloc0(sizeof(*caps));
430 caps->capability = i;
431 caps->state = s->capabilities[i];
432 QAPI_LIST_APPEND(tail, caps);
433 }
434
435 return head;
436}
45c1de13
JQ
437
438void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params,
439 Error **errp)
440{
441 MigrationState *s = migrate_get_current();
442 MigrationCapabilityStatusList *cap;
443 bool new_caps[MIGRATION_CAPABILITY__MAX];
444
445 if (migration_is_running(s->state)) {
446 error_setg(errp, QERR_MIGRATION_ACTIVE);
447 return;
448 }
449
450 memcpy(new_caps, s->capabilities, sizeof(new_caps));
451 for (cap = params; cap; cap = cap->next) {
452 new_caps[cap->value->capability] = cap->value->state;
453 }
454
455 if (!migrate_caps_check(s->capabilities, new_caps, errp)) {
456 return;
457 }
458
459 for (cap = params; cap; cap = cap->next) {
460 s->capabilities[cap->value->capability] = cap->value->state;
461 }
462}
1dfc4b9e
JQ
463
464/* parameters */
465
6f8be708
JQ
466bool migrate_block_incremental(void)
467{
468 MigrationState *s;
469
470 s = migrate_get_current();
471
472 return s->parameters.block_incremental;
473}
474
f94a858f
JQ
475uint32_t migrate_checkpoint_delay(void)
476{
477 MigrationState *s;
478
479 s = migrate_get_current();
480
481 return s->parameters.x_checkpoint_delay;
482}
483
1dfc4b9e
JQ
484int migrate_compress_level(void)
485{
486 MigrationState *s;
487
488 s = migrate_get_current();
489
490 return s->parameters.compress_level;
491}
492
493int migrate_compress_threads(void)
494{
495 MigrationState *s;
496
497 s = migrate_get_current();
498
499 return s->parameters.compress_threads;
500}
501
502int migrate_compress_wait_thread(void)
503{
504 MigrationState *s;
505
506 s = migrate_get_current();
507
508 return s->parameters.compress_wait_thread;
509}
510
511int migrate_decompress_threads(void)
512{
513 MigrationState *s;
514
515 s = migrate_get_current();
516
517 return s->parameters.decompress_threads;
518}
519
520int64_t migrate_max_postcopy_bandwidth(void)
521{
522 MigrationState *s;
523
524 s = migrate_get_current();
525
526 return s->parameters.max_postcopy_bandwidth;
527}
528
529int migrate_multifd_channels(void)
530{
531 MigrationState *s;
532
533 s = migrate_get_current();
534
535 return s->parameters.multifd_channels;
536}
537
538MultiFDCompression migrate_multifd_compression(void)
539{
540 MigrationState *s;
541
542 s = migrate_get_current();
543
544 assert(s->parameters.multifd_compression < MULTIFD_COMPRESSION__MAX);
545 return s->parameters.multifd_compression;
546}
547
548int migrate_multifd_zlib_level(void)
549{
550 MigrationState *s;
551
552 s = migrate_get_current();
553
554 return s->parameters.multifd_zlib_level;
555}
556
557int migrate_multifd_zstd_level(void)
558{
559 MigrationState *s;
560
561 s = migrate_get_current();
562
563 return s->parameters.multifd_zstd_level;
564}
565
6499efdb
JQ
566uint8_t migrate_throttle_trigger_threshold(void)
567{
568 MigrationState *s;
569
570 s = migrate_get_current();
571
572 return s->parameters.throttle_trigger_threshold;
573}
574
1dfc4b9e
JQ
575uint64_t migrate_xbzrle_cache_size(void)
576{
577 MigrationState *s;
578
579 s = migrate_get_current();
580
581 return s->parameters.xbzrle_cache_size;
582}