xref: /openbmc/qemu/migration/options.c (revision 61a174e227422790f1b264fed6df5c6686757edc)
11f0776f1SJuan Quintela /*
21f0776f1SJuan Quintela  * QEMU migration capabilities
31f0776f1SJuan Quintela  *
41f0776f1SJuan Quintela  * Copyright (c) 2012-2023 Red Hat Inc
51f0776f1SJuan Quintela  *
61f0776f1SJuan Quintela  * Authors:
71f0776f1SJuan Quintela  *   Orit Wasserman <owasserm@redhat.com>
81f0776f1SJuan Quintela  *   Juan Quintela <quintela@redhat.com>
91f0776f1SJuan Quintela  *
101f0776f1SJuan Quintela  * This work is licensed under the terms of the GNU GPL, version 2 or later.
111f0776f1SJuan Quintela  * See the COPYING file in the top-level directory.
121f0776f1SJuan Quintela  */
131f0776f1SJuan Quintela 
141f0776f1SJuan Quintela #include "qemu/osdep.h"
1509d6c965SJuan Quintela #include "exec/target_page.h"
169c894df3SJuan Quintela #include "qapi/clone-visitor.h"
1777608706SJuan Quintela #include "qapi/error.h"
184d0c6b69SJuan Quintela #include "qapi/qapi-commands-migration.h"
199c894df3SJuan Quintela #include "qapi/qapi-visit-migration.h"
20f80196b7SJuan Quintela #include "qapi/qmp/qerror.h"
2109d6c965SJuan Quintela #include "qapi/qmp/qnull.h"
2277608706SJuan Quintela #include "sysemu/runstate.h"
2309d6c965SJuan Quintela #include "migration/colo.h"
242682c4eeSJuan Quintela #include "migration/misc.h"
251f0776f1SJuan Quintela #include "migration.h"
2609d6c965SJuan Quintela #include "qemu-file.h"
2777608706SJuan Quintela #include "ram.h"
281f0776f1SJuan Quintela #include "options.h"
291f0776f1SJuan Quintela 
3009d6c965SJuan Quintela /* Maximum migrate downtime set to 2000 seconds */
3109d6c965SJuan Quintela #define MAX_MIGRATE_DOWNTIME_SECONDS 2000
3209d6c965SJuan Quintela #define MAX_MIGRATE_DOWNTIME (MAX_MIGRATE_DOWNTIME_SECONDS * 1000)
3309d6c965SJuan Quintela 
341f0776f1SJuan Quintela bool migrate_auto_converge(void)
351f0776f1SJuan Quintela {
361f0776f1SJuan Quintela     MigrationState *s;
371f0776f1SJuan Quintela 
381f0776f1SJuan Quintela     s = migrate_get_current();
391f0776f1SJuan Quintela 
401f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_AUTO_CONVERGE];
411f0776f1SJuan Quintela }
421f0776f1SJuan Quintela 
431f0776f1SJuan Quintela bool migrate_background_snapshot(void)
441f0776f1SJuan Quintela {
451f0776f1SJuan Quintela     MigrationState *s;
461f0776f1SJuan Quintela 
471f0776f1SJuan Quintela     s = migrate_get_current();
481f0776f1SJuan Quintela 
491f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT];
501f0776f1SJuan Quintela }
511f0776f1SJuan Quintela 
529d4b1e5fSJuan Quintela bool migrate_block(void)
539d4b1e5fSJuan Quintela {
549d4b1e5fSJuan Quintela     MigrationState *s;
559d4b1e5fSJuan Quintela 
569d4b1e5fSJuan Quintela     s = migrate_get_current();
579d4b1e5fSJuan Quintela 
589d4b1e5fSJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_BLOCK];
599d4b1e5fSJuan Quintela }
609d4b1e5fSJuan Quintela 
615e804644SJuan Quintela bool migrate_colo(void)
625e804644SJuan Quintela {
635e804644SJuan Quintela     MigrationState *s = migrate_get_current();
645e804644SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_X_COLO];
655e804644SJuan Quintela }
665e804644SJuan Quintela 
67a7a94d14SJuan Quintela bool migrate_compress(void)
68a7a94d14SJuan Quintela {
69a7a94d14SJuan Quintela     MigrationState *s;
70a7a94d14SJuan Quintela 
71a7a94d14SJuan Quintela     s = migrate_get_current();
72a7a94d14SJuan Quintela 
73a7a94d14SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_COMPRESS];
74a7a94d14SJuan Quintela }
75a7a94d14SJuan Quintela 
761f0776f1SJuan Quintela bool migrate_dirty_bitmaps(void)
771f0776f1SJuan Quintela {
781f0776f1SJuan Quintela     MigrationState *s;
791f0776f1SJuan Quintela 
801f0776f1SJuan Quintela     s = migrate_get_current();
811f0776f1SJuan Quintela 
821f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_DIRTY_BITMAPS];
831f0776f1SJuan Quintela }
841f0776f1SJuan Quintela 
85b890902cSJuan Quintela bool migrate_events(void)
86b890902cSJuan Quintela {
87b890902cSJuan Quintela     MigrationState *s;
88b890902cSJuan Quintela 
89b890902cSJuan Quintela     s = migrate_get_current();
90b890902cSJuan Quintela 
91b890902cSJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_EVENTS];
92b890902cSJuan Quintela }
93b890902cSJuan Quintela 
941f0776f1SJuan Quintela bool migrate_ignore_shared(void)
951f0776f1SJuan Quintela {
961f0776f1SJuan Quintela     MigrationState *s;
971f0776f1SJuan Quintela 
981f0776f1SJuan Quintela     s = migrate_get_current();
991f0776f1SJuan Quintela 
1001f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_X_IGNORE_SHARED];
1011f0776f1SJuan Quintela }
1021f0776f1SJuan Quintela 
1031f0776f1SJuan Quintela bool migrate_late_block_activate(void)
1041f0776f1SJuan Quintela {
1051f0776f1SJuan Quintela     MigrationState *s;
1061f0776f1SJuan Quintela 
1071f0776f1SJuan Quintela     s = migrate_get_current();
1081f0776f1SJuan Quintela 
1091f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE];
1101f0776f1SJuan Quintela }
1111f0776f1SJuan Quintela 
11251b07548SJuan Quintela bool migrate_multifd(void)
11351b07548SJuan Quintela {
11451b07548SJuan Quintela     MigrationState *s;
11551b07548SJuan Quintela 
11651b07548SJuan Quintela     s = migrate_get_current();
11751b07548SJuan Quintela 
11851b07548SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_MULTIFD];
11951b07548SJuan Quintela }
12051b07548SJuan Quintela 
1211f0776f1SJuan Quintela bool migrate_pause_before_switchover(void)
1221f0776f1SJuan Quintela {
1231f0776f1SJuan Quintela     MigrationState *s;
1241f0776f1SJuan Quintela 
1251f0776f1SJuan Quintela     s = migrate_get_current();
1261f0776f1SJuan Quintela 
1271f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER];
1281f0776f1SJuan Quintela }
1291f0776f1SJuan Quintela 
1301f0776f1SJuan Quintela bool migrate_postcopy_blocktime(void)
1311f0776f1SJuan Quintela {
1321f0776f1SJuan Quintela     MigrationState *s;
1331f0776f1SJuan Quintela 
1341f0776f1SJuan Quintela     s = migrate_get_current();
1351f0776f1SJuan Quintela 
1361f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME];
1371f0776f1SJuan Quintela }
1381f0776f1SJuan Quintela 
1391f0776f1SJuan Quintela bool migrate_postcopy_preempt(void)
1401f0776f1SJuan Quintela {
1411f0776f1SJuan Quintela     MigrationState *s;
1421f0776f1SJuan Quintela 
1431f0776f1SJuan Quintela     s = migrate_get_current();
1441f0776f1SJuan Quintela 
1451f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT];
1461f0776f1SJuan Quintela }
1471f0776f1SJuan Quintela 
1481f0776f1SJuan Quintela bool migrate_postcopy_ram(void)
1491f0776f1SJuan Quintela {
1501f0776f1SJuan Quintela     MigrationState *s;
1511f0776f1SJuan Quintela 
1521f0776f1SJuan Quintela     s = migrate_get_current();
1531f0776f1SJuan Quintela 
1541f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_RAM];
1551f0776f1SJuan Quintela }
1561f0776f1SJuan Quintela 
15717cba690SJuan Quintela bool migrate_rdma_pin_all(void)
15817cba690SJuan Quintela {
15917cba690SJuan Quintela     MigrationState *s = migrate_get_current();
16017cba690SJuan Quintela 
16117cba690SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_RDMA_PIN_ALL];
16217cba690SJuan Quintela }
16317cba690SJuan Quintela 
1641f0776f1SJuan Quintela bool migrate_release_ram(void)
1651f0776f1SJuan Quintela {
1661f0776f1SJuan Quintela     MigrationState *s;
1671f0776f1SJuan Quintela 
1681f0776f1SJuan Quintela     s = migrate_get_current();
1691f0776f1SJuan Quintela 
1701f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_RELEASE_RAM];
1711f0776f1SJuan Quintela }
1721f0776f1SJuan Quintela 
17338ad1110SJuan Quintela bool migrate_return_path(void)
17438ad1110SJuan Quintela {
17538ad1110SJuan Quintela     MigrationState *s;
17638ad1110SJuan Quintela 
17738ad1110SJuan Quintela     s = migrate_get_current();
17838ad1110SJuan Quintela 
17938ad1110SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_RETURN_PATH];
18038ad1110SJuan Quintela }
18138ad1110SJuan Quintela 
1821f0776f1SJuan Quintela bool migrate_validate_uuid(void)
1831f0776f1SJuan Quintela {
1841f0776f1SJuan Quintela     MigrationState *s;
1851f0776f1SJuan Quintela 
1861f0776f1SJuan Quintela     s = migrate_get_current();
1871f0776f1SJuan Quintela 
1881f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_VALIDATE_UUID];
1891f0776f1SJuan Quintela }
1901f0776f1SJuan Quintela 
19187dca0c9SJuan Quintela bool migrate_xbzrle(void)
19287dca0c9SJuan Quintela {
19387dca0c9SJuan Quintela     MigrationState *s;
19487dca0c9SJuan Quintela 
19587dca0c9SJuan Quintela     s = migrate_get_current();
19687dca0c9SJuan Quintela 
19787dca0c9SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_XBZRLE];
19887dca0c9SJuan Quintela }
19987dca0c9SJuan Quintela 
2001f0776f1SJuan Quintela bool migrate_zero_blocks(void)
2011f0776f1SJuan Quintela {
2021f0776f1SJuan Quintela     MigrationState *s;
2031f0776f1SJuan Quintela 
2041f0776f1SJuan Quintela     s = migrate_get_current();
2051f0776f1SJuan Quintela 
2061f0776f1SJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_ZERO_BLOCKS];
2071f0776f1SJuan Quintela }
208b4bc342cSJuan Quintela 
209b4bc342cSJuan Quintela bool migrate_zero_copy_send(void)
210b4bc342cSJuan Quintela {
211b4bc342cSJuan Quintela     MigrationState *s;
212b4bc342cSJuan Quintela 
213b4bc342cSJuan Quintela     s = migrate_get_current();
214b4bc342cSJuan Quintela 
215b4bc342cSJuan Quintela     return s->capabilities[MIGRATION_CAPABILITY_ZERO_COPY_SEND];
216b4bc342cSJuan Quintela }
217f774fde5SJuan Quintela 
218f774fde5SJuan Quintela /* pseudo capabilities */
219f774fde5SJuan Quintela 
220f774fde5SJuan Quintela bool migrate_postcopy(void)
221f774fde5SJuan Quintela {
222f774fde5SJuan Quintela     return migrate_postcopy_ram() || migrate_dirty_bitmaps();
223f774fde5SJuan Quintela }
224f774fde5SJuan Quintela 
22510d4703bSJuan Quintela bool migrate_tls(void)
22610d4703bSJuan Quintela {
22710d4703bSJuan Quintela     MigrationState *s;
22810d4703bSJuan Quintela 
22910d4703bSJuan Quintela     s = migrate_get_current();
23010d4703bSJuan Quintela 
23110d4703bSJuan Quintela     return s->parameters.tls_creds && *s->parameters.tls_creds;
23210d4703bSJuan Quintela }
23310d4703bSJuan Quintela 
23477608706SJuan Quintela typedef enum WriteTrackingSupport {
23577608706SJuan Quintela     WT_SUPPORT_UNKNOWN = 0,
23677608706SJuan Quintela     WT_SUPPORT_ABSENT,
23777608706SJuan Quintela     WT_SUPPORT_AVAILABLE,
23877608706SJuan Quintela     WT_SUPPORT_COMPATIBLE
23977608706SJuan Quintela } WriteTrackingSupport;
24077608706SJuan Quintela 
24177608706SJuan Quintela static
24277608706SJuan Quintela WriteTrackingSupport migrate_query_write_tracking(void)
24377608706SJuan Quintela {
24477608706SJuan Quintela     /* Check if kernel supports required UFFD features */
24577608706SJuan Quintela     if (!ram_write_tracking_available()) {
24677608706SJuan Quintela         return WT_SUPPORT_ABSENT;
24777608706SJuan Quintela     }
24877608706SJuan Quintela     /*
24977608706SJuan Quintela      * Check if current memory configuration is
25077608706SJuan Quintela      * compatible with required UFFD features.
25177608706SJuan Quintela      */
25277608706SJuan Quintela     if (!ram_write_tracking_compatible()) {
25377608706SJuan Quintela         return WT_SUPPORT_AVAILABLE;
25477608706SJuan Quintela     }
25577608706SJuan Quintela 
25677608706SJuan Quintela     return WT_SUPPORT_COMPATIBLE;
25777608706SJuan Quintela }
25877608706SJuan Quintela 
25977608706SJuan Quintela /* Migration capabilities set */
26077608706SJuan Quintela struct MigrateCapsSet {
26177608706SJuan Quintela     int size;                       /* Capability set size */
26277608706SJuan Quintela     MigrationCapability caps[];     /* Variadic array of capabilities */
26377608706SJuan Quintela };
26477608706SJuan Quintela typedef struct MigrateCapsSet MigrateCapsSet;
26577608706SJuan Quintela 
26677608706SJuan Quintela /* Define and initialize MigrateCapsSet */
26777608706SJuan Quintela #define INITIALIZE_MIGRATE_CAPS_SET(_name, ...)   \
26877608706SJuan Quintela     MigrateCapsSet _name = {    \
26977608706SJuan Quintela         .size = sizeof((int []) { __VA_ARGS__ }) / sizeof(int), \
27077608706SJuan Quintela         .caps = { __VA_ARGS__ } \
27177608706SJuan Quintela     }
27277608706SJuan Quintela 
27377608706SJuan Quintela /* Background-snapshot compatibility check list */
27477608706SJuan Quintela static const
27577608706SJuan Quintela INITIALIZE_MIGRATE_CAPS_SET(check_caps_background_snapshot,
27677608706SJuan Quintela     MIGRATION_CAPABILITY_POSTCOPY_RAM,
27777608706SJuan Quintela     MIGRATION_CAPABILITY_DIRTY_BITMAPS,
27877608706SJuan Quintela     MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME,
27977608706SJuan Quintela     MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE,
28077608706SJuan Quintela     MIGRATION_CAPABILITY_RETURN_PATH,
28177608706SJuan Quintela     MIGRATION_CAPABILITY_MULTIFD,
28277608706SJuan Quintela     MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER,
28377608706SJuan Quintela     MIGRATION_CAPABILITY_AUTO_CONVERGE,
28477608706SJuan Quintela     MIGRATION_CAPABILITY_RELEASE_RAM,
28577608706SJuan Quintela     MIGRATION_CAPABILITY_RDMA_PIN_ALL,
28677608706SJuan Quintela     MIGRATION_CAPABILITY_COMPRESS,
28777608706SJuan Quintela     MIGRATION_CAPABILITY_XBZRLE,
28877608706SJuan Quintela     MIGRATION_CAPABILITY_X_COLO,
28977608706SJuan Quintela     MIGRATION_CAPABILITY_VALIDATE_UUID,
29077608706SJuan Quintela     MIGRATION_CAPABILITY_ZERO_COPY_SEND);
29177608706SJuan Quintela 
29277608706SJuan Quintela /**
29377608706SJuan Quintela  * @migration_caps_check - check capability compatibility
29477608706SJuan Quintela  *
29577608706SJuan Quintela  * @old_caps: old capability list
29677608706SJuan Quintela  * @new_caps: new capability list
29777608706SJuan Quintela  * @errp: set *errp if the check failed, with reason
29877608706SJuan Quintela  *
29977608706SJuan Quintela  * Returns true if check passed, otherwise false.
30077608706SJuan Quintela  */
30177608706SJuan Quintela bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp)
30277608706SJuan Quintela {
30377608706SJuan Quintela     MigrationIncomingState *mis = migration_incoming_get_current();
30477608706SJuan Quintela 
30574c38cf7SPeter Xu     ERRP_GUARD();
30677608706SJuan Quintela #ifndef CONFIG_LIVE_BLOCK_MIGRATION
30777608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_BLOCK]) {
30877608706SJuan Quintela         error_setg(errp, "QEMU compiled without old-style (blk/-b, inc/-i) "
30977608706SJuan Quintela                    "block migration");
31077608706SJuan Quintela         error_append_hint(errp, "Use drive_mirror+NBD instead.\n");
31177608706SJuan Quintela         return false;
31277608706SJuan Quintela     }
31377608706SJuan Quintela #endif
31477608706SJuan Quintela 
31577608706SJuan Quintela #ifndef CONFIG_REPLICATION
31677608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_X_COLO]) {
31777608706SJuan Quintela         error_setg(errp, "QEMU compiled without replication module"
31877608706SJuan Quintela                    " can't enable COLO");
31977608706SJuan Quintela         error_append_hint(errp, "Please enable replication before COLO.\n");
32077608706SJuan Quintela         return false;
32177608706SJuan Quintela     }
32277608706SJuan Quintela #endif
32377608706SJuan Quintela 
32477608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) {
32577608706SJuan Quintela         /* This check is reasonably expensive, so only when it's being
32677608706SJuan Quintela          * set the first time, also it's only the destination that needs
32777608706SJuan Quintela          * special support.
32877608706SJuan Quintela          */
32977608706SJuan Quintela         if (!old_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM] &&
33077608706SJuan Quintela             runstate_check(RUN_STATE_INMIGRATE) &&
33174c38cf7SPeter Xu             !postcopy_ram_supported_by_host(mis, errp)) {
33274c38cf7SPeter Xu             error_prepend(errp, "Postcopy is not supported: ");
33377608706SJuan Quintela             return false;
33477608706SJuan Quintela         }
33577608706SJuan Quintela 
33677608706SJuan Quintela         if (new_caps[MIGRATION_CAPABILITY_X_IGNORE_SHARED]) {
33777608706SJuan Quintela             error_setg(errp, "Postcopy is not compatible with ignore-shared");
33877608706SJuan Quintela             return false;
33977608706SJuan Quintela         }
340b405dfffSLeonardo Bras 
341b405dfffSLeonardo Bras         if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) {
342b405dfffSLeonardo Bras             error_setg(errp, "Postcopy is not yet compatible with multifd");
343b405dfffSLeonardo Bras             return false;
344b405dfffSLeonardo Bras         }
34577608706SJuan Quintela     }
34677608706SJuan Quintela 
34777608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT]) {
34877608706SJuan Quintela         WriteTrackingSupport wt_support;
34977608706SJuan Quintela         int idx;
35077608706SJuan Quintela         /*
35177608706SJuan Quintela          * Check if 'background-snapshot' capability is supported by
35277608706SJuan Quintela          * host kernel and compatible with guest memory configuration.
35377608706SJuan Quintela          */
35477608706SJuan Quintela         wt_support = migrate_query_write_tracking();
35577608706SJuan Quintela         if (wt_support < WT_SUPPORT_AVAILABLE) {
35677608706SJuan Quintela             error_setg(errp, "Background-snapshot is not supported by host kernel");
35777608706SJuan Quintela             return false;
35877608706SJuan Quintela         }
35977608706SJuan Quintela         if (wt_support < WT_SUPPORT_COMPATIBLE) {
36077608706SJuan Quintela             error_setg(errp, "Background-snapshot is not compatible "
36177608706SJuan Quintela                     "with guest memory configuration");
36277608706SJuan Quintela             return false;
36377608706SJuan Quintela         }
36477608706SJuan Quintela 
36577608706SJuan Quintela         /*
36677608706SJuan Quintela          * Check if there are any migration capabilities
36777608706SJuan Quintela          * incompatible with 'background-snapshot'.
36877608706SJuan Quintela          */
36977608706SJuan Quintela         for (idx = 0; idx < check_caps_background_snapshot.size; idx++) {
37077608706SJuan Quintela             int incomp_cap = check_caps_background_snapshot.caps[idx];
37177608706SJuan Quintela             if (new_caps[incomp_cap]) {
37277608706SJuan Quintela                 error_setg(errp,
37377608706SJuan Quintela                         "Background-snapshot is not compatible with %s",
37477608706SJuan Quintela                         MigrationCapability_str(incomp_cap));
37577608706SJuan Quintela                 return false;
37677608706SJuan Quintela             }
37777608706SJuan Quintela         }
37877608706SJuan Quintela     }
37977608706SJuan Quintela 
38077608706SJuan Quintela #ifdef CONFIG_LINUX
38177608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND] &&
38277608706SJuan Quintela         (!new_caps[MIGRATION_CAPABILITY_MULTIFD] ||
38377608706SJuan Quintela          new_caps[MIGRATION_CAPABILITY_COMPRESS] ||
38477608706SJuan Quintela          new_caps[MIGRATION_CAPABILITY_XBZRLE] ||
38577608706SJuan Quintela          migrate_multifd_compression() ||
38610d4703bSJuan Quintela          migrate_tls())) {
38777608706SJuan Quintela         error_setg(errp,
38877608706SJuan Quintela                    "Zero copy only available for non-compressed non-TLS multifd migration");
38977608706SJuan Quintela         return false;
39077608706SJuan Quintela     }
39177608706SJuan Quintela #else
39277608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND]) {
39377608706SJuan Quintela         error_setg(errp,
39477608706SJuan Quintela                    "Zero copy currently only available on Linux");
39577608706SJuan Quintela         return false;
39677608706SJuan Quintela     }
39777608706SJuan Quintela #endif
39877608706SJuan Quintela 
39977608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT]) {
40077608706SJuan Quintela         if (!new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) {
40177608706SJuan Quintela             error_setg(errp, "Postcopy preempt requires postcopy-ram");
40277608706SJuan Quintela             return false;
40377608706SJuan Quintela         }
40477608706SJuan Quintela 
40577608706SJuan Quintela         /*
40677608706SJuan Quintela          * Preempt mode requires urgent pages to be sent in separate
40777608706SJuan Quintela          * channel, OTOH compression logic will disorder all pages into
40877608706SJuan Quintela          * different compression channels, which is not compatible with the
40977608706SJuan Quintela          * preempt assumptions on channel assignments.
41077608706SJuan Quintela          */
41177608706SJuan Quintela         if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) {
41277608706SJuan Quintela             error_setg(errp, "Postcopy preempt not compatible with compress");
41377608706SJuan Quintela             return false;
41477608706SJuan Quintela         }
41577608706SJuan Quintela     }
41677608706SJuan Quintela 
41777608706SJuan Quintela     if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) {
41877608706SJuan Quintela         if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) {
41977608706SJuan Quintela             error_setg(errp, "Multifd is not compatible with compress");
42077608706SJuan Quintela             return false;
42177608706SJuan Quintela         }
42277608706SJuan Quintela     }
42377608706SJuan Quintela 
42477608706SJuan Quintela     return true;
42577608706SJuan Quintela }
4264d0c6b69SJuan Quintela 
427f80196b7SJuan Quintela bool migrate_cap_set(int cap, bool value, Error **errp)
428f80196b7SJuan Quintela {
429f80196b7SJuan Quintela     MigrationState *s = migrate_get_current();
430f80196b7SJuan Quintela     bool new_caps[MIGRATION_CAPABILITY__MAX];
431f80196b7SJuan Quintela 
432f80196b7SJuan Quintela     if (migration_is_running(s->state)) {
433f80196b7SJuan Quintela         error_setg(errp, QERR_MIGRATION_ACTIVE);
434f80196b7SJuan Quintela         return false;
435f80196b7SJuan Quintela     }
436f80196b7SJuan Quintela 
437f80196b7SJuan Quintela     memcpy(new_caps, s->capabilities, sizeof(new_caps));
438f80196b7SJuan Quintela     new_caps[cap] = value;
439f80196b7SJuan Quintela 
440f80196b7SJuan Quintela     if (!migrate_caps_check(s->capabilities, new_caps, errp)) {
441f80196b7SJuan Quintela         return false;
442f80196b7SJuan Quintela     }
443f80196b7SJuan Quintela     s->capabilities[cap] = value;
444f80196b7SJuan Quintela     return true;
445f80196b7SJuan Quintela }
446f80196b7SJuan Quintela 
4474d0c6b69SJuan Quintela MigrationCapabilityStatusList *qmp_query_migrate_capabilities(Error **errp)
4484d0c6b69SJuan Quintela {
4494d0c6b69SJuan Quintela     MigrationCapabilityStatusList *head = NULL, **tail = &head;
4504d0c6b69SJuan Quintela     MigrationCapabilityStatus *caps;
4514d0c6b69SJuan Quintela     MigrationState *s = migrate_get_current();
4524d0c6b69SJuan Quintela     int i;
4534d0c6b69SJuan Quintela 
4544d0c6b69SJuan Quintela     for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
4554d0c6b69SJuan Quintela #ifndef CONFIG_LIVE_BLOCK_MIGRATION
4564d0c6b69SJuan Quintela         if (i == MIGRATION_CAPABILITY_BLOCK) {
4574d0c6b69SJuan Quintela             continue;
4584d0c6b69SJuan Quintela         }
4594d0c6b69SJuan Quintela #endif
4604d0c6b69SJuan Quintela         caps = g_malloc0(sizeof(*caps));
4614d0c6b69SJuan Quintela         caps->capability = i;
4624d0c6b69SJuan Quintela         caps->state = s->capabilities[i];
4634d0c6b69SJuan Quintela         QAPI_LIST_APPEND(tail, caps);
4644d0c6b69SJuan Quintela     }
4654d0c6b69SJuan Quintela 
4664d0c6b69SJuan Quintela     return head;
4674d0c6b69SJuan Quintela }
46845c1de13SJuan Quintela 
46945c1de13SJuan Quintela void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params,
47045c1de13SJuan Quintela                                   Error **errp)
47145c1de13SJuan Quintela {
47245c1de13SJuan Quintela     MigrationState *s = migrate_get_current();
47345c1de13SJuan Quintela     MigrationCapabilityStatusList *cap;
47445c1de13SJuan Quintela     bool new_caps[MIGRATION_CAPABILITY__MAX];
47545c1de13SJuan Quintela 
47645c1de13SJuan Quintela     if (migration_is_running(s->state)) {
47745c1de13SJuan Quintela         error_setg(errp, QERR_MIGRATION_ACTIVE);
47845c1de13SJuan Quintela         return;
47945c1de13SJuan Quintela     }
48045c1de13SJuan Quintela 
48145c1de13SJuan Quintela     memcpy(new_caps, s->capabilities, sizeof(new_caps));
48245c1de13SJuan Quintela     for (cap = params; cap; cap = cap->next) {
48345c1de13SJuan Quintela         new_caps[cap->value->capability] = cap->value->state;
48445c1de13SJuan Quintela     }
48545c1de13SJuan Quintela 
48645c1de13SJuan Quintela     if (!migrate_caps_check(s->capabilities, new_caps, errp)) {
48745c1de13SJuan Quintela         return;
48845c1de13SJuan Quintela     }
48945c1de13SJuan Quintela 
49045c1de13SJuan Quintela     for (cap = params; cap; cap = cap->next) {
49145c1de13SJuan Quintela         s->capabilities[cap->value->capability] = cap->value->state;
49245c1de13SJuan Quintela     }
49345c1de13SJuan Quintela }
4941dfc4b9eSJuan Quintela 
4951dfc4b9eSJuan Quintela /* parameters */
4961dfc4b9eSJuan Quintela 
4976f8be708SJuan Quintela bool migrate_block_incremental(void)
4986f8be708SJuan Quintela {
4996f8be708SJuan Quintela     MigrationState *s;
5006f8be708SJuan Quintela 
5016f8be708SJuan Quintela     s = migrate_get_current();
5026f8be708SJuan Quintela 
5036f8be708SJuan Quintela     return s->parameters.block_incremental;
5046f8be708SJuan Quintela }
5056f8be708SJuan Quintela 
506f94a858fSJuan Quintela uint32_t migrate_checkpoint_delay(void)
507f94a858fSJuan Quintela {
508f94a858fSJuan Quintela     MigrationState *s;
509f94a858fSJuan Quintela 
510f94a858fSJuan Quintela     s = migrate_get_current();
511f94a858fSJuan Quintela 
512f94a858fSJuan Quintela     return s->parameters.x_checkpoint_delay;
513f94a858fSJuan Quintela }
514f94a858fSJuan Quintela 
5151dfc4b9eSJuan Quintela int migrate_compress_level(void)
5161dfc4b9eSJuan Quintela {
5171dfc4b9eSJuan Quintela     MigrationState *s;
5181dfc4b9eSJuan Quintela 
5191dfc4b9eSJuan Quintela     s = migrate_get_current();
5201dfc4b9eSJuan Quintela 
5211dfc4b9eSJuan Quintela     return s->parameters.compress_level;
5221dfc4b9eSJuan Quintela }
5231dfc4b9eSJuan Quintela 
5241dfc4b9eSJuan Quintela int migrate_compress_threads(void)
5251dfc4b9eSJuan Quintela {
5261dfc4b9eSJuan Quintela     MigrationState *s;
5271dfc4b9eSJuan Quintela 
5281dfc4b9eSJuan Quintela     s = migrate_get_current();
5291dfc4b9eSJuan Quintela 
5301dfc4b9eSJuan Quintela     return s->parameters.compress_threads;
5311dfc4b9eSJuan Quintela }
5321dfc4b9eSJuan Quintela 
5331dfc4b9eSJuan Quintela int migrate_compress_wait_thread(void)
5341dfc4b9eSJuan Quintela {
5351dfc4b9eSJuan Quintela     MigrationState *s;
5361dfc4b9eSJuan Quintela 
5371dfc4b9eSJuan Quintela     s = migrate_get_current();
5381dfc4b9eSJuan Quintela 
5391dfc4b9eSJuan Quintela     return s->parameters.compress_wait_thread;
5401dfc4b9eSJuan Quintela }
5411dfc4b9eSJuan Quintela 
5429605c2acSJuan Quintela uint8_t migrate_cpu_throttle_increment(void)
5439605c2acSJuan Quintela {
5449605c2acSJuan Quintela     MigrationState *s;
5459605c2acSJuan Quintela 
5469605c2acSJuan Quintela     s = migrate_get_current();
5479605c2acSJuan Quintela 
5489605c2acSJuan Quintela     return s->parameters.cpu_throttle_increment;
5499605c2acSJuan Quintela }
5509605c2acSJuan Quintela 
5512a8ec380SJuan Quintela uint8_t migrate_cpu_throttle_initial(void)
5522a8ec380SJuan Quintela {
5532a8ec380SJuan Quintela     MigrationState *s;
5542a8ec380SJuan Quintela 
5552a8ec380SJuan Quintela     s = migrate_get_current();
5562a8ec380SJuan Quintela 
5572a8ec380SJuan Quintela     return s->parameters.cpu_throttle_initial;
5582a8ec380SJuan Quintela }
5592a8ec380SJuan Quintela 
560873f674cSJuan Quintela bool migrate_cpu_throttle_tailslow(void)
561873f674cSJuan Quintela {
562873f674cSJuan Quintela     MigrationState *s;
563873f674cSJuan Quintela 
564873f674cSJuan Quintela     s = migrate_get_current();
565873f674cSJuan Quintela 
566873f674cSJuan Quintela     return s->parameters.cpu_throttle_tailslow;
567873f674cSJuan Quintela }
568873f674cSJuan Quintela 
5691dfc4b9eSJuan Quintela int migrate_decompress_threads(void)
5701dfc4b9eSJuan Quintela {
5711dfc4b9eSJuan Quintela     MigrationState *s;
5721dfc4b9eSJuan Quintela 
5731dfc4b9eSJuan Quintela     s = migrate_get_current();
5741dfc4b9eSJuan Quintela 
5751dfc4b9eSJuan Quintela     return s->parameters.decompress_threads;
5761dfc4b9eSJuan Quintela }
5771dfc4b9eSJuan Quintela 
57824155bd0SJuan Quintela uint8_t migrate_max_cpu_throttle(void)
57924155bd0SJuan Quintela {
58024155bd0SJuan Quintela     MigrationState *s;
58124155bd0SJuan Quintela 
58224155bd0SJuan Quintela     s = migrate_get_current();
58324155bd0SJuan Quintela 
58424155bd0SJuan Quintela     return s->parameters.max_cpu_throttle;
58524155bd0SJuan Quintela }
58624155bd0SJuan Quintela 
5879c894df3SJuan Quintela uint64_t migrate_max_bandwidth(void)
5889c894df3SJuan Quintela {
5899c894df3SJuan Quintela     MigrationState *s;
5909c894df3SJuan Quintela 
5919c894df3SJuan Quintela     s = migrate_get_current();
5929c894df3SJuan Quintela 
5939c894df3SJuan Quintela     return s->parameters.max_bandwidth;
5949c894df3SJuan Quintela }
5959c894df3SJuan Quintela 
5961dfc4b9eSJuan Quintela int64_t migrate_max_postcopy_bandwidth(void)
5971dfc4b9eSJuan Quintela {
5981dfc4b9eSJuan Quintela     MigrationState *s;
5991dfc4b9eSJuan Quintela 
6001dfc4b9eSJuan Quintela     s = migrate_get_current();
6011dfc4b9eSJuan Quintela 
6021dfc4b9eSJuan Quintela     return s->parameters.max_postcopy_bandwidth;
6031dfc4b9eSJuan Quintela }
6041dfc4b9eSJuan Quintela 
6051dfc4b9eSJuan Quintela int migrate_multifd_channels(void)
6061dfc4b9eSJuan Quintela {
6071dfc4b9eSJuan Quintela     MigrationState *s;
6081dfc4b9eSJuan Quintela 
6091dfc4b9eSJuan Quintela     s = migrate_get_current();
6101dfc4b9eSJuan Quintela 
6111dfc4b9eSJuan Quintela     return s->parameters.multifd_channels;
6121dfc4b9eSJuan Quintela }
6131dfc4b9eSJuan Quintela 
6141dfc4b9eSJuan Quintela MultiFDCompression migrate_multifd_compression(void)
6151dfc4b9eSJuan Quintela {
6161dfc4b9eSJuan Quintela     MigrationState *s;
6171dfc4b9eSJuan Quintela 
6181dfc4b9eSJuan Quintela     s = migrate_get_current();
6191dfc4b9eSJuan Quintela 
6201dfc4b9eSJuan Quintela     assert(s->parameters.multifd_compression < MULTIFD_COMPRESSION__MAX);
6211dfc4b9eSJuan Quintela     return s->parameters.multifd_compression;
6221dfc4b9eSJuan Quintela }
6231dfc4b9eSJuan Quintela 
6241dfc4b9eSJuan Quintela int migrate_multifd_zlib_level(void)
6251dfc4b9eSJuan Quintela {
6261dfc4b9eSJuan Quintela     MigrationState *s;
6271dfc4b9eSJuan Quintela 
6281dfc4b9eSJuan Quintela     s = migrate_get_current();
6291dfc4b9eSJuan Quintela 
6301dfc4b9eSJuan Quintela     return s->parameters.multifd_zlib_level;
6311dfc4b9eSJuan Quintela }
6321dfc4b9eSJuan Quintela 
6331dfc4b9eSJuan Quintela int migrate_multifd_zstd_level(void)
6341dfc4b9eSJuan Quintela {
6351dfc4b9eSJuan Quintela     MigrationState *s;
6361dfc4b9eSJuan Quintela 
6371dfc4b9eSJuan Quintela     s = migrate_get_current();
6381dfc4b9eSJuan Quintela 
6391dfc4b9eSJuan Quintela     return s->parameters.multifd_zstd_level;
6401dfc4b9eSJuan Quintela }
6411dfc4b9eSJuan Quintela 
6426499efdbSJuan Quintela uint8_t migrate_throttle_trigger_threshold(void)
6436499efdbSJuan Quintela {
6446499efdbSJuan Quintela     MigrationState *s;
6456499efdbSJuan Quintela 
6466499efdbSJuan Quintela     s = migrate_get_current();
6476499efdbSJuan Quintela 
6486499efdbSJuan Quintela     return s->parameters.throttle_trigger_threshold;
6496499efdbSJuan Quintela }
6506499efdbSJuan Quintela 
6511dfc4b9eSJuan Quintela uint64_t migrate_xbzrle_cache_size(void)
6521dfc4b9eSJuan Quintela {
6531dfc4b9eSJuan Quintela     MigrationState *s;
6541dfc4b9eSJuan Quintela 
6551dfc4b9eSJuan Quintela     s = migrate_get_current();
6561dfc4b9eSJuan Quintela 
6571dfc4b9eSJuan Quintela     return s->parameters.xbzrle_cache_size;
6581dfc4b9eSJuan Quintela }
6592682c4eeSJuan Quintela 
6602682c4eeSJuan Quintela /* parameters helpers */
6612682c4eeSJuan Quintela 
6622682c4eeSJuan Quintela AnnounceParameters *migrate_announce_params(void)
6632682c4eeSJuan Quintela {
6642682c4eeSJuan Quintela     static AnnounceParameters ap;
6652682c4eeSJuan Quintela 
6662682c4eeSJuan Quintela     MigrationState *s = migrate_get_current();
6672682c4eeSJuan Quintela 
6682682c4eeSJuan Quintela     ap.initial = s->parameters.announce_initial;
6692682c4eeSJuan Quintela     ap.max = s->parameters.announce_max;
6702682c4eeSJuan Quintela     ap.rounds = s->parameters.announce_rounds;
6712682c4eeSJuan Quintela     ap.step = s->parameters.announce_step;
6722682c4eeSJuan Quintela 
6732682c4eeSJuan Quintela     return &ap;
6742682c4eeSJuan Quintela }
6759c894df3SJuan Quintela 
6769c894df3SJuan Quintela MigrationParameters *qmp_query_migrate_parameters(Error **errp)
6779c894df3SJuan Quintela {
6789c894df3SJuan Quintela     MigrationParameters *params;
6799c894df3SJuan Quintela     MigrationState *s = migrate_get_current();
6809c894df3SJuan Quintela 
6819c894df3SJuan Quintela     /* TODO use QAPI_CLONE() instead of duplicating it inline */
6829c894df3SJuan Quintela     params = g_malloc0(sizeof(*params));
6839c894df3SJuan Quintela     params->has_compress_level = true;
6849c894df3SJuan Quintela     params->compress_level = s->parameters.compress_level;
6859c894df3SJuan Quintela     params->has_compress_threads = true;
6869c894df3SJuan Quintela     params->compress_threads = s->parameters.compress_threads;
6879c894df3SJuan Quintela     params->has_compress_wait_thread = true;
6889c894df3SJuan Quintela     params->compress_wait_thread = s->parameters.compress_wait_thread;
6899c894df3SJuan Quintela     params->has_decompress_threads = true;
6909c894df3SJuan Quintela     params->decompress_threads = s->parameters.decompress_threads;
6919c894df3SJuan Quintela     params->has_throttle_trigger_threshold = true;
6929c894df3SJuan Quintela     params->throttle_trigger_threshold = s->parameters.throttle_trigger_threshold;
6939c894df3SJuan Quintela     params->has_cpu_throttle_initial = true;
6949c894df3SJuan Quintela     params->cpu_throttle_initial = s->parameters.cpu_throttle_initial;
6959c894df3SJuan Quintela     params->has_cpu_throttle_increment = true;
6969c894df3SJuan Quintela     params->cpu_throttle_increment = s->parameters.cpu_throttle_increment;
6979c894df3SJuan Quintela     params->has_cpu_throttle_tailslow = true;
6989c894df3SJuan Quintela     params->cpu_throttle_tailslow = s->parameters.cpu_throttle_tailslow;
6999c894df3SJuan Quintela     params->tls_creds = g_strdup(s->parameters.tls_creds);
7009c894df3SJuan Quintela     params->tls_hostname = g_strdup(s->parameters.tls_hostname);
7019c894df3SJuan Quintela     params->tls_authz = g_strdup(s->parameters.tls_authz ?
7029c894df3SJuan Quintela                                  s->parameters.tls_authz : "");
7039c894df3SJuan Quintela     params->has_max_bandwidth = true;
7049c894df3SJuan Quintela     params->max_bandwidth = s->parameters.max_bandwidth;
7059c894df3SJuan Quintela     params->has_downtime_limit = true;
7069c894df3SJuan Quintela     params->downtime_limit = s->parameters.downtime_limit;
7079c894df3SJuan Quintela     params->has_x_checkpoint_delay = true;
7089c894df3SJuan Quintela     params->x_checkpoint_delay = s->parameters.x_checkpoint_delay;
7099c894df3SJuan Quintela     params->has_block_incremental = true;
7109c894df3SJuan Quintela     params->block_incremental = s->parameters.block_incremental;
7119c894df3SJuan Quintela     params->has_multifd_channels = true;
7129c894df3SJuan Quintela     params->multifd_channels = s->parameters.multifd_channels;
7139c894df3SJuan Quintela     params->has_multifd_compression = true;
7149c894df3SJuan Quintela     params->multifd_compression = s->parameters.multifd_compression;
7159c894df3SJuan Quintela     params->has_multifd_zlib_level = true;
7169c894df3SJuan Quintela     params->multifd_zlib_level = s->parameters.multifd_zlib_level;
7179c894df3SJuan Quintela     params->has_multifd_zstd_level = true;
7189c894df3SJuan Quintela     params->multifd_zstd_level = s->parameters.multifd_zstd_level;
7199c894df3SJuan Quintela     params->has_xbzrle_cache_size = true;
7209c894df3SJuan Quintela     params->xbzrle_cache_size = s->parameters.xbzrle_cache_size;
7219c894df3SJuan Quintela     params->has_max_postcopy_bandwidth = true;
7229c894df3SJuan Quintela     params->max_postcopy_bandwidth = s->parameters.max_postcopy_bandwidth;
7239c894df3SJuan Quintela     params->has_max_cpu_throttle = true;
7249c894df3SJuan Quintela     params->max_cpu_throttle = s->parameters.max_cpu_throttle;
7259c894df3SJuan Quintela     params->has_announce_initial = true;
7269c894df3SJuan Quintela     params->announce_initial = s->parameters.announce_initial;
7279c894df3SJuan Quintela     params->has_announce_max = true;
7289c894df3SJuan Quintela     params->announce_max = s->parameters.announce_max;
7299c894df3SJuan Quintela     params->has_announce_rounds = true;
7309c894df3SJuan Quintela     params->announce_rounds = s->parameters.announce_rounds;
7319c894df3SJuan Quintela     params->has_announce_step = true;
7329c894df3SJuan Quintela     params->announce_step = s->parameters.announce_step;
7339c894df3SJuan Quintela 
7349c894df3SJuan Quintela     if (s->parameters.has_block_bitmap_mapping) {
7359c894df3SJuan Quintela         params->has_block_bitmap_mapping = true;
7369c894df3SJuan Quintela         params->block_bitmap_mapping =
7379c894df3SJuan Quintela             QAPI_CLONE(BitmapMigrationNodeAliasList,
7389c894df3SJuan Quintela                        s->parameters.block_bitmap_mapping);
7399c894df3SJuan Quintela     }
7409c894df3SJuan Quintela 
7419c894df3SJuan Quintela     return params;
7429c894df3SJuan Quintela }
74309d6c965SJuan Quintela 
744*61a174e2SJuan Quintela void migrate_params_init(MigrationParameters *params)
745*61a174e2SJuan Quintela {
746*61a174e2SJuan Quintela     params->tls_hostname = g_strdup("");
747*61a174e2SJuan Quintela     params->tls_creds = g_strdup("");
748*61a174e2SJuan Quintela 
749*61a174e2SJuan Quintela     /* Set has_* up only for parameter checks */
750*61a174e2SJuan Quintela     params->has_compress_level = true;
751*61a174e2SJuan Quintela     params->has_compress_threads = true;
752*61a174e2SJuan Quintela     params->has_compress_wait_thread = true;
753*61a174e2SJuan Quintela     params->has_decompress_threads = true;
754*61a174e2SJuan Quintela     params->has_throttle_trigger_threshold = true;
755*61a174e2SJuan Quintela     params->has_cpu_throttle_initial = true;
756*61a174e2SJuan Quintela     params->has_cpu_throttle_increment = true;
757*61a174e2SJuan Quintela     params->has_cpu_throttle_tailslow = true;
758*61a174e2SJuan Quintela     params->has_max_bandwidth = true;
759*61a174e2SJuan Quintela     params->has_downtime_limit = true;
760*61a174e2SJuan Quintela     params->has_x_checkpoint_delay = true;
761*61a174e2SJuan Quintela     params->has_block_incremental = true;
762*61a174e2SJuan Quintela     params->has_multifd_channels = true;
763*61a174e2SJuan Quintela     params->has_multifd_compression = true;
764*61a174e2SJuan Quintela     params->has_multifd_zlib_level = true;
765*61a174e2SJuan Quintela     params->has_multifd_zstd_level = true;
766*61a174e2SJuan Quintela     params->has_xbzrle_cache_size = true;
767*61a174e2SJuan Quintela     params->has_max_postcopy_bandwidth = true;
768*61a174e2SJuan Quintela     params->has_max_cpu_throttle = true;
769*61a174e2SJuan Quintela     params->has_announce_initial = true;
770*61a174e2SJuan Quintela     params->has_announce_max = true;
771*61a174e2SJuan Quintela     params->has_announce_rounds = true;
772*61a174e2SJuan Quintela     params->has_announce_step = true;
773*61a174e2SJuan Quintela }
774*61a174e2SJuan Quintela 
77509d6c965SJuan Quintela /*
77609d6c965SJuan Quintela  * Check whether the parameters are valid. Error will be put into errp
77709d6c965SJuan Quintela  * (if provided). Return true if valid, otherwise false.
77809d6c965SJuan Quintela  */
77909d6c965SJuan Quintela bool migrate_params_check(MigrationParameters *params, Error **errp)
78009d6c965SJuan Quintela {
78109d6c965SJuan Quintela     if (params->has_compress_level &&
78209d6c965SJuan Quintela         (params->compress_level > 9)) {
78309d6c965SJuan Quintela         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "compress_level",
78409d6c965SJuan Quintela                    "a value between 0 and 9");
78509d6c965SJuan Quintela         return false;
78609d6c965SJuan Quintela     }
78709d6c965SJuan Quintela 
78809d6c965SJuan Quintela     if (params->has_compress_threads && (params->compress_threads < 1)) {
78909d6c965SJuan Quintela         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
79009d6c965SJuan Quintela                    "compress_threads",
79109d6c965SJuan Quintela                    "a value between 1 and 255");
79209d6c965SJuan Quintela         return false;
79309d6c965SJuan Quintela     }
79409d6c965SJuan Quintela 
79509d6c965SJuan Quintela     if (params->has_decompress_threads && (params->decompress_threads < 1)) {
79609d6c965SJuan Quintela         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
79709d6c965SJuan Quintela                    "decompress_threads",
79809d6c965SJuan Quintela                    "a value between 1 and 255");
79909d6c965SJuan Quintela         return false;
80009d6c965SJuan Quintela     }
80109d6c965SJuan Quintela 
80209d6c965SJuan Quintela     if (params->has_throttle_trigger_threshold &&
80309d6c965SJuan Quintela         (params->throttle_trigger_threshold < 1 ||
80409d6c965SJuan Quintela          params->throttle_trigger_threshold > 100)) {
80509d6c965SJuan Quintela         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
80609d6c965SJuan Quintela                    "throttle_trigger_threshold",
80709d6c965SJuan Quintela                    "an integer in the range of 1 to 100");
80809d6c965SJuan Quintela         return false;
80909d6c965SJuan Quintela     }
81009d6c965SJuan Quintela 
81109d6c965SJuan Quintela     if (params->has_cpu_throttle_initial &&
81209d6c965SJuan Quintela         (params->cpu_throttle_initial < 1 ||
81309d6c965SJuan Quintela          params->cpu_throttle_initial > 99)) {
81409d6c965SJuan Quintela         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
81509d6c965SJuan Quintela                    "cpu_throttle_initial",
81609d6c965SJuan Quintela                    "an integer in the range of 1 to 99");
81709d6c965SJuan Quintela         return false;
81809d6c965SJuan Quintela     }
81909d6c965SJuan Quintela 
82009d6c965SJuan Quintela     if (params->has_cpu_throttle_increment &&
82109d6c965SJuan Quintela         (params->cpu_throttle_increment < 1 ||
82209d6c965SJuan Quintela          params->cpu_throttle_increment > 99)) {
82309d6c965SJuan Quintela         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
82409d6c965SJuan Quintela                    "cpu_throttle_increment",
82509d6c965SJuan Quintela                    "an integer in the range of 1 to 99");
82609d6c965SJuan Quintela         return false;
82709d6c965SJuan Quintela     }
82809d6c965SJuan Quintela 
82909d6c965SJuan Quintela     if (params->has_max_bandwidth && (params->max_bandwidth > SIZE_MAX)) {
83009d6c965SJuan Quintela         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
83109d6c965SJuan Quintela                    "max_bandwidth",
83209d6c965SJuan Quintela                    "an integer in the range of 0 to "stringify(SIZE_MAX)
83309d6c965SJuan Quintela                    " bytes/second");
83409d6c965SJuan Quintela         return false;
83509d6c965SJuan Quintela     }
83609d6c965SJuan Quintela 
83709d6c965SJuan Quintela     if (params->has_downtime_limit &&
83809d6c965SJuan Quintela         (params->downtime_limit > MAX_MIGRATE_DOWNTIME)) {
83909d6c965SJuan Quintela         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
84009d6c965SJuan Quintela                    "downtime_limit",
84109d6c965SJuan Quintela                    "an integer in the range of 0 to "
84209d6c965SJuan Quintela                     stringify(MAX_MIGRATE_DOWNTIME)" ms");
84309d6c965SJuan Quintela         return false;
84409d6c965SJuan Quintela     }
84509d6c965SJuan Quintela 
84609d6c965SJuan Quintela     /* x_checkpoint_delay is now always positive */
84709d6c965SJuan Quintela 
84809d6c965SJuan Quintela     if (params->has_multifd_channels && (params->multifd_channels < 1)) {
84909d6c965SJuan Quintela         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
85009d6c965SJuan Quintela                    "multifd_channels",
85109d6c965SJuan Quintela                    "a value between 1 and 255");
85209d6c965SJuan Quintela         return false;
85309d6c965SJuan Quintela     }
85409d6c965SJuan Quintela 
85509d6c965SJuan Quintela     if (params->has_multifd_zlib_level &&
85609d6c965SJuan Quintela         (params->multifd_zlib_level > 9)) {
85709d6c965SJuan Quintela         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "multifd_zlib_level",
85809d6c965SJuan Quintela                    "a value between 0 and 9");
85909d6c965SJuan Quintela         return false;
86009d6c965SJuan Quintela     }
86109d6c965SJuan Quintela 
86209d6c965SJuan Quintela     if (params->has_multifd_zstd_level &&
86309d6c965SJuan Quintela         (params->multifd_zstd_level > 20)) {
86409d6c965SJuan Quintela         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "multifd_zstd_level",
86509d6c965SJuan Quintela                    "a value between 0 and 20");
86609d6c965SJuan Quintela         return false;
86709d6c965SJuan Quintela     }
86809d6c965SJuan Quintela 
86909d6c965SJuan Quintela     if (params->has_xbzrle_cache_size &&
87009d6c965SJuan Quintela         (params->xbzrle_cache_size < qemu_target_page_size() ||
87109d6c965SJuan Quintela          !is_power_of_2(params->xbzrle_cache_size))) {
87209d6c965SJuan Quintela         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
87309d6c965SJuan Quintela                    "xbzrle_cache_size",
87409d6c965SJuan Quintela                    "a power of two no less than the target page size");
87509d6c965SJuan Quintela         return false;
87609d6c965SJuan Quintela     }
87709d6c965SJuan Quintela 
87809d6c965SJuan Quintela     if (params->has_max_cpu_throttle &&
87909d6c965SJuan Quintela         (params->max_cpu_throttle < params->cpu_throttle_initial ||
88009d6c965SJuan Quintela          params->max_cpu_throttle > 99)) {
88109d6c965SJuan Quintela         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
88209d6c965SJuan Quintela                    "max_cpu_throttle",
88309d6c965SJuan Quintela                    "an integer in the range of cpu_throttle_initial to 99");
88409d6c965SJuan Quintela         return false;
88509d6c965SJuan Quintela     }
88609d6c965SJuan Quintela 
88709d6c965SJuan Quintela     if (params->has_announce_initial &&
88809d6c965SJuan Quintela         params->announce_initial > 100000) {
88909d6c965SJuan Quintela         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
89009d6c965SJuan Quintela                    "announce_initial",
89109d6c965SJuan Quintela                    "a value between 0 and 100000");
89209d6c965SJuan Quintela         return false;
89309d6c965SJuan Quintela     }
89409d6c965SJuan Quintela     if (params->has_announce_max &&
89509d6c965SJuan Quintela         params->announce_max > 100000) {
89609d6c965SJuan Quintela         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
89709d6c965SJuan Quintela                    "announce_max",
89809d6c965SJuan Quintela                    "a value between 0 and 100000");
89909d6c965SJuan Quintela        return false;
90009d6c965SJuan Quintela     }
90109d6c965SJuan Quintela     if (params->has_announce_rounds &&
90209d6c965SJuan Quintela         params->announce_rounds > 1000) {
90309d6c965SJuan Quintela         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
90409d6c965SJuan Quintela                    "announce_rounds",
90509d6c965SJuan Quintela                    "a value between 0 and 1000");
90609d6c965SJuan Quintela        return false;
90709d6c965SJuan Quintela     }
90809d6c965SJuan Quintela     if (params->has_announce_step &&
90909d6c965SJuan Quintela         (params->announce_step < 1 ||
91009d6c965SJuan Quintela         params->announce_step > 10000)) {
91109d6c965SJuan Quintela         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
91209d6c965SJuan Quintela                    "announce_step",
91309d6c965SJuan Quintela                    "a value between 0 and 10000");
91409d6c965SJuan Quintela        return false;
91509d6c965SJuan Quintela     }
91609d6c965SJuan Quintela 
91709d6c965SJuan Quintela     if (params->has_block_bitmap_mapping &&
91809d6c965SJuan Quintela         !check_dirty_bitmap_mig_alias_map(params->block_bitmap_mapping, errp)) {
91909d6c965SJuan Quintela         error_prepend(errp, "Invalid mapping given for block-bitmap-mapping: ");
92009d6c965SJuan Quintela         return false;
92109d6c965SJuan Quintela     }
92209d6c965SJuan Quintela 
92309d6c965SJuan Quintela #ifdef CONFIG_LINUX
92409d6c965SJuan Quintela     if (migrate_zero_copy_send() &&
92509d6c965SJuan Quintela         ((params->has_multifd_compression && params->multifd_compression) ||
92609d6c965SJuan Quintela          (params->tls_creds && *params->tls_creds))) {
92709d6c965SJuan Quintela         error_setg(errp,
92809d6c965SJuan Quintela                    "Zero copy only available for non-compressed non-TLS multifd migration");
92909d6c965SJuan Quintela         return false;
93009d6c965SJuan Quintela     }
93109d6c965SJuan Quintela #endif
93209d6c965SJuan Quintela 
93309d6c965SJuan Quintela     return true;
93409d6c965SJuan Quintela }
93509d6c965SJuan Quintela 
93609d6c965SJuan Quintela static void migrate_params_test_apply(MigrateSetParameters *params,
93709d6c965SJuan Quintela                                       MigrationParameters *dest)
93809d6c965SJuan Quintela {
93909d6c965SJuan Quintela     *dest = migrate_get_current()->parameters;
94009d6c965SJuan Quintela 
94109d6c965SJuan Quintela     /* TODO use QAPI_CLONE() instead of duplicating it inline */
94209d6c965SJuan Quintela 
94309d6c965SJuan Quintela     if (params->has_compress_level) {
94409d6c965SJuan Quintela         dest->compress_level = params->compress_level;
94509d6c965SJuan Quintela     }
94609d6c965SJuan Quintela 
94709d6c965SJuan Quintela     if (params->has_compress_threads) {
94809d6c965SJuan Quintela         dest->compress_threads = params->compress_threads;
94909d6c965SJuan Quintela     }
95009d6c965SJuan Quintela 
95109d6c965SJuan Quintela     if (params->has_compress_wait_thread) {
95209d6c965SJuan Quintela         dest->compress_wait_thread = params->compress_wait_thread;
95309d6c965SJuan Quintela     }
95409d6c965SJuan Quintela 
95509d6c965SJuan Quintela     if (params->has_decompress_threads) {
95609d6c965SJuan Quintela         dest->decompress_threads = params->decompress_threads;
95709d6c965SJuan Quintela     }
95809d6c965SJuan Quintela 
95909d6c965SJuan Quintela     if (params->has_throttle_trigger_threshold) {
96009d6c965SJuan Quintela         dest->throttle_trigger_threshold = params->throttle_trigger_threshold;
96109d6c965SJuan Quintela     }
96209d6c965SJuan Quintela 
96309d6c965SJuan Quintela     if (params->has_cpu_throttle_initial) {
96409d6c965SJuan Quintela         dest->cpu_throttle_initial = params->cpu_throttle_initial;
96509d6c965SJuan Quintela     }
96609d6c965SJuan Quintela 
96709d6c965SJuan Quintela     if (params->has_cpu_throttle_increment) {
96809d6c965SJuan Quintela         dest->cpu_throttle_increment = params->cpu_throttle_increment;
96909d6c965SJuan Quintela     }
97009d6c965SJuan Quintela 
97109d6c965SJuan Quintela     if (params->has_cpu_throttle_tailslow) {
97209d6c965SJuan Quintela         dest->cpu_throttle_tailslow = params->cpu_throttle_tailslow;
97309d6c965SJuan Quintela     }
97409d6c965SJuan Quintela 
97509d6c965SJuan Quintela     if (params->tls_creds) {
97609d6c965SJuan Quintela         assert(params->tls_creds->type == QTYPE_QSTRING);
97709d6c965SJuan Quintela         dest->tls_creds = params->tls_creds->u.s;
97809d6c965SJuan Quintela     }
97909d6c965SJuan Quintela 
98009d6c965SJuan Quintela     if (params->tls_hostname) {
98109d6c965SJuan Quintela         assert(params->tls_hostname->type == QTYPE_QSTRING);
98209d6c965SJuan Quintela         dest->tls_hostname = params->tls_hostname->u.s;
98309d6c965SJuan Quintela     }
98409d6c965SJuan Quintela 
98509d6c965SJuan Quintela     if (params->has_max_bandwidth) {
98609d6c965SJuan Quintela         dest->max_bandwidth = params->max_bandwidth;
98709d6c965SJuan Quintela     }
98809d6c965SJuan Quintela 
98909d6c965SJuan Quintela     if (params->has_downtime_limit) {
99009d6c965SJuan Quintela         dest->downtime_limit = params->downtime_limit;
99109d6c965SJuan Quintela     }
99209d6c965SJuan Quintela 
99309d6c965SJuan Quintela     if (params->has_x_checkpoint_delay) {
99409d6c965SJuan Quintela         dest->x_checkpoint_delay = params->x_checkpoint_delay;
99509d6c965SJuan Quintela     }
99609d6c965SJuan Quintela 
99709d6c965SJuan Quintela     if (params->has_block_incremental) {
99809d6c965SJuan Quintela         dest->block_incremental = params->block_incremental;
99909d6c965SJuan Quintela     }
100009d6c965SJuan Quintela     if (params->has_multifd_channels) {
100109d6c965SJuan Quintela         dest->multifd_channels = params->multifd_channels;
100209d6c965SJuan Quintela     }
100309d6c965SJuan Quintela     if (params->has_multifd_compression) {
100409d6c965SJuan Quintela         dest->multifd_compression = params->multifd_compression;
100509d6c965SJuan Quintela     }
100609d6c965SJuan Quintela     if (params->has_xbzrle_cache_size) {
100709d6c965SJuan Quintela         dest->xbzrle_cache_size = params->xbzrle_cache_size;
100809d6c965SJuan Quintela     }
100909d6c965SJuan Quintela     if (params->has_max_postcopy_bandwidth) {
101009d6c965SJuan Quintela         dest->max_postcopy_bandwidth = params->max_postcopy_bandwidth;
101109d6c965SJuan Quintela     }
101209d6c965SJuan Quintela     if (params->has_max_cpu_throttle) {
101309d6c965SJuan Quintela         dest->max_cpu_throttle = params->max_cpu_throttle;
101409d6c965SJuan Quintela     }
101509d6c965SJuan Quintela     if (params->has_announce_initial) {
101609d6c965SJuan Quintela         dest->announce_initial = params->announce_initial;
101709d6c965SJuan Quintela     }
101809d6c965SJuan Quintela     if (params->has_announce_max) {
101909d6c965SJuan Quintela         dest->announce_max = params->announce_max;
102009d6c965SJuan Quintela     }
102109d6c965SJuan Quintela     if (params->has_announce_rounds) {
102209d6c965SJuan Quintela         dest->announce_rounds = params->announce_rounds;
102309d6c965SJuan Quintela     }
102409d6c965SJuan Quintela     if (params->has_announce_step) {
102509d6c965SJuan Quintela         dest->announce_step = params->announce_step;
102609d6c965SJuan Quintela     }
102709d6c965SJuan Quintela 
102809d6c965SJuan Quintela     if (params->has_block_bitmap_mapping) {
102909d6c965SJuan Quintela         dest->has_block_bitmap_mapping = true;
103009d6c965SJuan Quintela         dest->block_bitmap_mapping = params->block_bitmap_mapping;
103109d6c965SJuan Quintela     }
103209d6c965SJuan Quintela }
103309d6c965SJuan Quintela 
103409d6c965SJuan Quintela static void migrate_params_apply(MigrateSetParameters *params, Error **errp)
103509d6c965SJuan Quintela {
103609d6c965SJuan Quintela     MigrationState *s = migrate_get_current();
103709d6c965SJuan Quintela 
103809d6c965SJuan Quintela     /* TODO use QAPI_CLONE() instead of duplicating it inline */
103909d6c965SJuan Quintela 
104009d6c965SJuan Quintela     if (params->has_compress_level) {
104109d6c965SJuan Quintela         s->parameters.compress_level = params->compress_level;
104209d6c965SJuan Quintela     }
104309d6c965SJuan Quintela 
104409d6c965SJuan Quintela     if (params->has_compress_threads) {
104509d6c965SJuan Quintela         s->parameters.compress_threads = params->compress_threads;
104609d6c965SJuan Quintela     }
104709d6c965SJuan Quintela 
104809d6c965SJuan Quintela     if (params->has_compress_wait_thread) {
104909d6c965SJuan Quintela         s->parameters.compress_wait_thread = params->compress_wait_thread;
105009d6c965SJuan Quintela     }
105109d6c965SJuan Quintela 
105209d6c965SJuan Quintela     if (params->has_decompress_threads) {
105309d6c965SJuan Quintela         s->parameters.decompress_threads = params->decompress_threads;
105409d6c965SJuan Quintela     }
105509d6c965SJuan Quintela 
105609d6c965SJuan Quintela     if (params->has_throttle_trigger_threshold) {
105709d6c965SJuan Quintela         s->parameters.throttle_trigger_threshold = params->throttle_trigger_threshold;
105809d6c965SJuan Quintela     }
105909d6c965SJuan Quintela 
106009d6c965SJuan Quintela     if (params->has_cpu_throttle_initial) {
106109d6c965SJuan Quintela         s->parameters.cpu_throttle_initial = params->cpu_throttle_initial;
106209d6c965SJuan Quintela     }
106309d6c965SJuan Quintela 
106409d6c965SJuan Quintela     if (params->has_cpu_throttle_increment) {
106509d6c965SJuan Quintela         s->parameters.cpu_throttle_increment = params->cpu_throttle_increment;
106609d6c965SJuan Quintela     }
106709d6c965SJuan Quintela 
106809d6c965SJuan Quintela     if (params->has_cpu_throttle_tailslow) {
106909d6c965SJuan Quintela         s->parameters.cpu_throttle_tailslow = params->cpu_throttle_tailslow;
107009d6c965SJuan Quintela     }
107109d6c965SJuan Quintela 
107209d6c965SJuan Quintela     if (params->tls_creds) {
107309d6c965SJuan Quintela         g_free(s->parameters.tls_creds);
107409d6c965SJuan Quintela         assert(params->tls_creds->type == QTYPE_QSTRING);
107509d6c965SJuan Quintela         s->parameters.tls_creds = g_strdup(params->tls_creds->u.s);
107609d6c965SJuan Quintela     }
107709d6c965SJuan Quintela 
107809d6c965SJuan Quintela     if (params->tls_hostname) {
107909d6c965SJuan Quintela         g_free(s->parameters.tls_hostname);
108009d6c965SJuan Quintela         assert(params->tls_hostname->type == QTYPE_QSTRING);
108109d6c965SJuan Quintela         s->parameters.tls_hostname = g_strdup(params->tls_hostname->u.s);
108209d6c965SJuan Quintela     }
108309d6c965SJuan Quintela 
108409d6c965SJuan Quintela     if (params->tls_authz) {
108509d6c965SJuan Quintela         g_free(s->parameters.tls_authz);
108609d6c965SJuan Quintela         assert(params->tls_authz->type == QTYPE_QSTRING);
108709d6c965SJuan Quintela         s->parameters.tls_authz = g_strdup(params->tls_authz->u.s);
108809d6c965SJuan Quintela     }
108909d6c965SJuan Quintela 
109009d6c965SJuan Quintela     if (params->has_max_bandwidth) {
109109d6c965SJuan Quintela         s->parameters.max_bandwidth = params->max_bandwidth;
109209d6c965SJuan Quintela         if (s->to_dst_file && !migration_in_postcopy()) {
109309d6c965SJuan Quintela             qemu_file_set_rate_limit(s->to_dst_file,
109409d6c965SJuan Quintela                                 s->parameters.max_bandwidth / XFER_LIMIT_RATIO);
109509d6c965SJuan Quintela         }
109609d6c965SJuan Quintela     }
109709d6c965SJuan Quintela 
109809d6c965SJuan Quintela     if (params->has_downtime_limit) {
109909d6c965SJuan Quintela         s->parameters.downtime_limit = params->downtime_limit;
110009d6c965SJuan Quintela     }
110109d6c965SJuan Quintela 
110209d6c965SJuan Quintela     if (params->has_x_checkpoint_delay) {
110309d6c965SJuan Quintela         s->parameters.x_checkpoint_delay = params->x_checkpoint_delay;
110409d6c965SJuan Quintela         if (migration_in_colo_state()) {
110509d6c965SJuan Quintela             colo_checkpoint_notify(s);
110609d6c965SJuan Quintela         }
110709d6c965SJuan Quintela     }
110809d6c965SJuan Quintela 
110909d6c965SJuan Quintela     if (params->has_block_incremental) {
111009d6c965SJuan Quintela         s->parameters.block_incremental = params->block_incremental;
111109d6c965SJuan Quintela     }
111209d6c965SJuan Quintela     if (params->has_multifd_channels) {
111309d6c965SJuan Quintela         s->parameters.multifd_channels = params->multifd_channels;
111409d6c965SJuan Quintela     }
111509d6c965SJuan Quintela     if (params->has_multifd_compression) {
111609d6c965SJuan Quintela         s->parameters.multifd_compression = params->multifd_compression;
111709d6c965SJuan Quintela     }
111809d6c965SJuan Quintela     if (params->has_xbzrle_cache_size) {
111909d6c965SJuan Quintela         s->parameters.xbzrle_cache_size = params->xbzrle_cache_size;
112009d6c965SJuan Quintela         xbzrle_cache_resize(params->xbzrle_cache_size, errp);
112109d6c965SJuan Quintela     }
112209d6c965SJuan Quintela     if (params->has_max_postcopy_bandwidth) {
112309d6c965SJuan Quintela         s->parameters.max_postcopy_bandwidth = params->max_postcopy_bandwidth;
112409d6c965SJuan Quintela         if (s->to_dst_file && migration_in_postcopy()) {
112509d6c965SJuan Quintela             qemu_file_set_rate_limit(s->to_dst_file,
112609d6c965SJuan Quintela                     s->parameters.max_postcopy_bandwidth / XFER_LIMIT_RATIO);
112709d6c965SJuan Quintela         }
112809d6c965SJuan Quintela     }
112909d6c965SJuan Quintela     if (params->has_max_cpu_throttle) {
113009d6c965SJuan Quintela         s->parameters.max_cpu_throttle = params->max_cpu_throttle;
113109d6c965SJuan Quintela     }
113209d6c965SJuan Quintela     if (params->has_announce_initial) {
113309d6c965SJuan Quintela         s->parameters.announce_initial = params->announce_initial;
113409d6c965SJuan Quintela     }
113509d6c965SJuan Quintela     if (params->has_announce_max) {
113609d6c965SJuan Quintela         s->parameters.announce_max = params->announce_max;
113709d6c965SJuan Quintela     }
113809d6c965SJuan Quintela     if (params->has_announce_rounds) {
113909d6c965SJuan Quintela         s->parameters.announce_rounds = params->announce_rounds;
114009d6c965SJuan Quintela     }
114109d6c965SJuan Quintela     if (params->has_announce_step) {
114209d6c965SJuan Quintela         s->parameters.announce_step = params->announce_step;
114309d6c965SJuan Quintela     }
114409d6c965SJuan Quintela 
114509d6c965SJuan Quintela     if (params->has_block_bitmap_mapping) {
114609d6c965SJuan Quintela         qapi_free_BitmapMigrationNodeAliasList(
114709d6c965SJuan Quintela             s->parameters.block_bitmap_mapping);
114809d6c965SJuan Quintela 
114909d6c965SJuan Quintela         s->parameters.has_block_bitmap_mapping = true;
115009d6c965SJuan Quintela         s->parameters.block_bitmap_mapping =
115109d6c965SJuan Quintela             QAPI_CLONE(BitmapMigrationNodeAliasList,
115209d6c965SJuan Quintela                        params->block_bitmap_mapping);
115309d6c965SJuan Quintela     }
115409d6c965SJuan Quintela }
115509d6c965SJuan Quintela 
115609d6c965SJuan Quintela void qmp_migrate_set_parameters(MigrateSetParameters *params, Error **errp)
115709d6c965SJuan Quintela {
115809d6c965SJuan Quintela     MigrationParameters tmp;
115909d6c965SJuan Quintela 
116009d6c965SJuan Quintela     /* TODO Rewrite "" to null instead */
116109d6c965SJuan Quintela     if (params->tls_creds
116209d6c965SJuan Quintela         && params->tls_creds->type == QTYPE_QNULL) {
116309d6c965SJuan Quintela         qobject_unref(params->tls_creds->u.n);
116409d6c965SJuan Quintela         params->tls_creds->type = QTYPE_QSTRING;
116509d6c965SJuan Quintela         params->tls_creds->u.s = strdup("");
116609d6c965SJuan Quintela     }
116709d6c965SJuan Quintela     /* TODO Rewrite "" to null instead */
116809d6c965SJuan Quintela     if (params->tls_hostname
116909d6c965SJuan Quintela         && params->tls_hostname->type == QTYPE_QNULL) {
117009d6c965SJuan Quintela         qobject_unref(params->tls_hostname->u.n);
117109d6c965SJuan Quintela         params->tls_hostname->type = QTYPE_QSTRING;
117209d6c965SJuan Quintela         params->tls_hostname->u.s = strdup("");
117309d6c965SJuan Quintela     }
117409d6c965SJuan Quintela 
117509d6c965SJuan Quintela     migrate_params_test_apply(params, &tmp);
117609d6c965SJuan Quintela 
117709d6c965SJuan Quintela     if (!migrate_params_check(&tmp, errp)) {
117809d6c965SJuan Quintela         /* Invalid parameter */
117909d6c965SJuan Quintela         return;
118009d6c965SJuan Quintela     }
118109d6c965SJuan Quintela 
118209d6c965SJuan Quintela     migrate_params_apply(params, errp);
118309d6c965SJuan Quintela }
1184