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" 159c894df3SJuan Quintela #include "qapi/clone-visitor.h" 1677608706SJuan Quintela #include "qapi/error.h" 174d0c6b69SJuan Quintela #include "qapi/qapi-commands-migration.h" 189c894df3SJuan Quintela #include "qapi/qapi-visit-migration.h" 19f80196b7SJuan Quintela #include "qapi/qmp/qerror.h" 2077608706SJuan Quintela #include "sysemu/runstate.h" 212682c4eeSJuan Quintela #include "migration/misc.h" 221f0776f1SJuan Quintela #include "migration.h" 2377608706SJuan Quintela #include "ram.h" 241f0776f1SJuan Quintela #include "options.h" 251f0776f1SJuan Quintela 261f0776f1SJuan Quintela bool migrate_auto_converge(void) 271f0776f1SJuan Quintela { 281f0776f1SJuan Quintela MigrationState *s; 291f0776f1SJuan Quintela 301f0776f1SJuan Quintela s = migrate_get_current(); 311f0776f1SJuan Quintela 321f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_AUTO_CONVERGE]; 331f0776f1SJuan Quintela } 341f0776f1SJuan Quintela 351f0776f1SJuan Quintela bool migrate_background_snapshot(void) 361f0776f1SJuan Quintela { 371f0776f1SJuan Quintela MigrationState *s; 381f0776f1SJuan Quintela 391f0776f1SJuan Quintela s = migrate_get_current(); 401f0776f1SJuan Quintela 411f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT]; 421f0776f1SJuan Quintela } 431f0776f1SJuan Quintela 449d4b1e5fSJuan Quintela bool migrate_block(void) 459d4b1e5fSJuan Quintela { 469d4b1e5fSJuan Quintela MigrationState *s; 479d4b1e5fSJuan Quintela 489d4b1e5fSJuan Quintela s = migrate_get_current(); 499d4b1e5fSJuan Quintela 509d4b1e5fSJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_BLOCK]; 519d4b1e5fSJuan Quintela } 529d4b1e5fSJuan Quintela 535e804644SJuan Quintela bool migrate_colo(void) 545e804644SJuan Quintela { 555e804644SJuan Quintela MigrationState *s = migrate_get_current(); 565e804644SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_X_COLO]; 575e804644SJuan Quintela } 585e804644SJuan Quintela 59a7a94d14SJuan Quintela bool migrate_compress(void) 60a7a94d14SJuan Quintela { 61a7a94d14SJuan Quintela MigrationState *s; 62a7a94d14SJuan Quintela 63a7a94d14SJuan Quintela s = migrate_get_current(); 64a7a94d14SJuan Quintela 65a7a94d14SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_COMPRESS]; 66a7a94d14SJuan Quintela } 67a7a94d14SJuan Quintela 681f0776f1SJuan Quintela bool migrate_dirty_bitmaps(void) 691f0776f1SJuan Quintela { 701f0776f1SJuan Quintela MigrationState *s; 711f0776f1SJuan Quintela 721f0776f1SJuan Quintela s = migrate_get_current(); 731f0776f1SJuan Quintela 741f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_DIRTY_BITMAPS]; 751f0776f1SJuan Quintela } 761f0776f1SJuan Quintela 77b890902cSJuan Quintela bool migrate_events(void) 78b890902cSJuan Quintela { 79b890902cSJuan Quintela MigrationState *s; 80b890902cSJuan Quintela 81b890902cSJuan Quintela s = migrate_get_current(); 82b890902cSJuan Quintela 83b890902cSJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_EVENTS]; 84b890902cSJuan Quintela } 85b890902cSJuan Quintela 861f0776f1SJuan Quintela bool migrate_ignore_shared(void) 871f0776f1SJuan Quintela { 881f0776f1SJuan Quintela MigrationState *s; 891f0776f1SJuan Quintela 901f0776f1SJuan Quintela s = migrate_get_current(); 911f0776f1SJuan Quintela 921f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_X_IGNORE_SHARED]; 931f0776f1SJuan Quintela } 941f0776f1SJuan Quintela 951f0776f1SJuan Quintela bool migrate_late_block_activate(void) 961f0776f1SJuan Quintela { 971f0776f1SJuan Quintela MigrationState *s; 981f0776f1SJuan Quintela 991f0776f1SJuan Quintela s = migrate_get_current(); 1001f0776f1SJuan Quintela 1011f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE]; 1021f0776f1SJuan Quintela } 1031f0776f1SJuan Quintela 10451b07548SJuan Quintela bool migrate_multifd(void) 10551b07548SJuan Quintela { 10651b07548SJuan Quintela MigrationState *s; 10751b07548SJuan Quintela 10851b07548SJuan Quintela s = migrate_get_current(); 10951b07548SJuan Quintela 11051b07548SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_MULTIFD]; 11151b07548SJuan Quintela } 11251b07548SJuan Quintela 1131f0776f1SJuan Quintela bool migrate_pause_before_switchover(void) 1141f0776f1SJuan Quintela { 1151f0776f1SJuan Quintela MigrationState *s; 1161f0776f1SJuan Quintela 1171f0776f1SJuan Quintela s = migrate_get_current(); 1181f0776f1SJuan Quintela 1191f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER]; 1201f0776f1SJuan Quintela } 1211f0776f1SJuan Quintela 1221f0776f1SJuan Quintela bool migrate_postcopy_blocktime(void) 1231f0776f1SJuan Quintela { 1241f0776f1SJuan Quintela MigrationState *s; 1251f0776f1SJuan Quintela 1261f0776f1SJuan Quintela s = migrate_get_current(); 1271f0776f1SJuan Quintela 1281f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME]; 1291f0776f1SJuan Quintela } 1301f0776f1SJuan Quintela 1311f0776f1SJuan Quintela bool migrate_postcopy_preempt(void) 1321f0776f1SJuan Quintela { 1331f0776f1SJuan Quintela MigrationState *s; 1341f0776f1SJuan Quintela 1351f0776f1SJuan Quintela s = migrate_get_current(); 1361f0776f1SJuan Quintela 1371f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT]; 1381f0776f1SJuan Quintela } 1391f0776f1SJuan Quintela 1401f0776f1SJuan Quintela bool migrate_postcopy_ram(void) 1411f0776f1SJuan Quintela { 1421f0776f1SJuan Quintela MigrationState *s; 1431f0776f1SJuan Quintela 1441f0776f1SJuan Quintela s = migrate_get_current(); 1451f0776f1SJuan Quintela 1461f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_RAM]; 1471f0776f1SJuan Quintela } 1481f0776f1SJuan Quintela 14917cba690SJuan Quintela bool migrate_rdma_pin_all(void) 15017cba690SJuan Quintela { 15117cba690SJuan Quintela MigrationState *s = migrate_get_current(); 15217cba690SJuan Quintela 15317cba690SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_RDMA_PIN_ALL]; 15417cba690SJuan Quintela } 15517cba690SJuan Quintela 1561f0776f1SJuan Quintela bool migrate_release_ram(void) 1571f0776f1SJuan Quintela { 1581f0776f1SJuan Quintela MigrationState *s; 1591f0776f1SJuan Quintela 1601f0776f1SJuan Quintela s = migrate_get_current(); 1611f0776f1SJuan Quintela 1621f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_RELEASE_RAM]; 1631f0776f1SJuan Quintela } 1641f0776f1SJuan Quintela 16538ad1110SJuan Quintela bool migrate_return_path(void) 16638ad1110SJuan Quintela { 16738ad1110SJuan Quintela MigrationState *s; 16838ad1110SJuan Quintela 16938ad1110SJuan Quintela s = migrate_get_current(); 17038ad1110SJuan Quintela 17138ad1110SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_RETURN_PATH]; 17238ad1110SJuan Quintela } 17338ad1110SJuan Quintela 1741f0776f1SJuan Quintela bool migrate_validate_uuid(void) 1751f0776f1SJuan Quintela { 1761f0776f1SJuan Quintela MigrationState *s; 1771f0776f1SJuan Quintela 1781f0776f1SJuan Quintela s = migrate_get_current(); 1791f0776f1SJuan Quintela 1801f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_VALIDATE_UUID]; 1811f0776f1SJuan Quintela } 1821f0776f1SJuan Quintela 18387dca0c9SJuan Quintela bool migrate_xbzrle(void) 18487dca0c9SJuan Quintela { 18587dca0c9SJuan Quintela MigrationState *s; 18687dca0c9SJuan Quintela 18787dca0c9SJuan Quintela s = migrate_get_current(); 18887dca0c9SJuan Quintela 18987dca0c9SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_XBZRLE]; 19087dca0c9SJuan Quintela } 19187dca0c9SJuan Quintela 1921f0776f1SJuan Quintela bool migrate_zero_blocks(void) 1931f0776f1SJuan Quintela { 1941f0776f1SJuan Quintela MigrationState *s; 1951f0776f1SJuan Quintela 1961f0776f1SJuan Quintela s = migrate_get_current(); 1971f0776f1SJuan Quintela 1981f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_ZERO_BLOCKS]; 1991f0776f1SJuan Quintela } 200b4bc342cSJuan Quintela 201b4bc342cSJuan Quintela bool migrate_zero_copy_send(void) 202b4bc342cSJuan Quintela { 203b4bc342cSJuan Quintela MigrationState *s; 204b4bc342cSJuan Quintela 205b4bc342cSJuan Quintela s = migrate_get_current(); 206b4bc342cSJuan Quintela 207b4bc342cSJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_ZERO_COPY_SEND]; 208b4bc342cSJuan Quintela } 209f774fde5SJuan Quintela 210f774fde5SJuan Quintela /* pseudo capabilities */ 211f774fde5SJuan Quintela 212f774fde5SJuan Quintela bool migrate_postcopy(void) 213f774fde5SJuan Quintela { 214f774fde5SJuan Quintela return migrate_postcopy_ram() || migrate_dirty_bitmaps(); 215f774fde5SJuan Quintela } 216f774fde5SJuan Quintela 21777608706SJuan Quintela typedef enum WriteTrackingSupport { 21877608706SJuan Quintela WT_SUPPORT_UNKNOWN = 0, 21977608706SJuan Quintela WT_SUPPORT_ABSENT, 22077608706SJuan Quintela WT_SUPPORT_AVAILABLE, 22177608706SJuan Quintela WT_SUPPORT_COMPATIBLE 22277608706SJuan Quintela } WriteTrackingSupport; 22377608706SJuan Quintela 22477608706SJuan Quintela static 22577608706SJuan Quintela WriteTrackingSupport migrate_query_write_tracking(void) 22677608706SJuan Quintela { 22777608706SJuan Quintela /* Check if kernel supports required UFFD features */ 22877608706SJuan Quintela if (!ram_write_tracking_available()) { 22977608706SJuan Quintela return WT_SUPPORT_ABSENT; 23077608706SJuan Quintela } 23177608706SJuan Quintela /* 23277608706SJuan Quintela * Check if current memory configuration is 23377608706SJuan Quintela * compatible with required UFFD features. 23477608706SJuan Quintela */ 23577608706SJuan Quintela if (!ram_write_tracking_compatible()) { 23677608706SJuan Quintela return WT_SUPPORT_AVAILABLE; 23777608706SJuan Quintela } 23877608706SJuan Quintela 23977608706SJuan Quintela return WT_SUPPORT_COMPATIBLE; 24077608706SJuan Quintela } 24177608706SJuan Quintela 24277608706SJuan Quintela /* Migration capabilities set */ 24377608706SJuan Quintela struct MigrateCapsSet { 24477608706SJuan Quintela int size; /* Capability set size */ 24577608706SJuan Quintela MigrationCapability caps[]; /* Variadic array of capabilities */ 24677608706SJuan Quintela }; 24777608706SJuan Quintela typedef struct MigrateCapsSet MigrateCapsSet; 24877608706SJuan Quintela 24977608706SJuan Quintela /* Define and initialize MigrateCapsSet */ 25077608706SJuan Quintela #define INITIALIZE_MIGRATE_CAPS_SET(_name, ...) \ 25177608706SJuan Quintela MigrateCapsSet _name = { \ 25277608706SJuan Quintela .size = sizeof((int []) { __VA_ARGS__ }) / sizeof(int), \ 25377608706SJuan Quintela .caps = { __VA_ARGS__ } \ 25477608706SJuan Quintela } 25577608706SJuan Quintela 25677608706SJuan Quintela /* Background-snapshot compatibility check list */ 25777608706SJuan Quintela static const 25877608706SJuan Quintela INITIALIZE_MIGRATE_CAPS_SET(check_caps_background_snapshot, 25977608706SJuan Quintela MIGRATION_CAPABILITY_POSTCOPY_RAM, 26077608706SJuan Quintela MIGRATION_CAPABILITY_DIRTY_BITMAPS, 26177608706SJuan Quintela MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME, 26277608706SJuan Quintela MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE, 26377608706SJuan Quintela MIGRATION_CAPABILITY_RETURN_PATH, 26477608706SJuan Quintela MIGRATION_CAPABILITY_MULTIFD, 26577608706SJuan Quintela MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER, 26677608706SJuan Quintela MIGRATION_CAPABILITY_AUTO_CONVERGE, 26777608706SJuan Quintela MIGRATION_CAPABILITY_RELEASE_RAM, 26877608706SJuan Quintela MIGRATION_CAPABILITY_RDMA_PIN_ALL, 26977608706SJuan Quintela MIGRATION_CAPABILITY_COMPRESS, 27077608706SJuan Quintela MIGRATION_CAPABILITY_XBZRLE, 27177608706SJuan Quintela MIGRATION_CAPABILITY_X_COLO, 27277608706SJuan Quintela MIGRATION_CAPABILITY_VALIDATE_UUID, 27377608706SJuan Quintela MIGRATION_CAPABILITY_ZERO_COPY_SEND); 27477608706SJuan Quintela 27577608706SJuan Quintela /** 27677608706SJuan Quintela * @migration_caps_check - check capability compatibility 27777608706SJuan Quintela * 27877608706SJuan Quintela * @old_caps: old capability list 27977608706SJuan Quintela * @new_caps: new capability list 28077608706SJuan Quintela * @errp: set *errp if the check failed, with reason 28177608706SJuan Quintela * 28277608706SJuan Quintela * Returns true if check passed, otherwise false. 28377608706SJuan Quintela */ 28477608706SJuan Quintela bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp) 28577608706SJuan Quintela { 28677608706SJuan Quintela MigrationIncomingState *mis = migration_incoming_get_current(); 28777608706SJuan Quintela 28877608706SJuan Quintela #ifndef CONFIG_LIVE_BLOCK_MIGRATION 28977608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_BLOCK]) { 29077608706SJuan Quintela error_setg(errp, "QEMU compiled without old-style (blk/-b, inc/-i) " 29177608706SJuan Quintela "block migration"); 29277608706SJuan Quintela error_append_hint(errp, "Use drive_mirror+NBD instead.\n"); 29377608706SJuan Quintela return false; 29477608706SJuan Quintela } 29577608706SJuan Quintela #endif 29677608706SJuan Quintela 29777608706SJuan Quintela #ifndef CONFIG_REPLICATION 29877608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_X_COLO]) { 29977608706SJuan Quintela error_setg(errp, "QEMU compiled without replication module" 30077608706SJuan Quintela " can't enable COLO"); 30177608706SJuan Quintela error_append_hint(errp, "Please enable replication before COLO.\n"); 30277608706SJuan Quintela return false; 30377608706SJuan Quintela } 30477608706SJuan Quintela #endif 30577608706SJuan Quintela 30677608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) { 30777608706SJuan Quintela /* This check is reasonably expensive, so only when it's being 30877608706SJuan Quintela * set the first time, also it's only the destination that needs 30977608706SJuan Quintela * special support. 31077608706SJuan Quintela */ 31177608706SJuan Quintela if (!old_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM] && 31277608706SJuan Quintela runstate_check(RUN_STATE_INMIGRATE) && 31377608706SJuan Quintela !postcopy_ram_supported_by_host(mis)) { 31477608706SJuan Quintela /* postcopy_ram_supported_by_host will have emitted a more 31577608706SJuan Quintela * detailed message 31677608706SJuan Quintela */ 31777608706SJuan Quintela error_setg(errp, "Postcopy is not supported"); 31877608706SJuan Quintela return false; 31977608706SJuan Quintela } 32077608706SJuan Quintela 32177608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_X_IGNORE_SHARED]) { 32277608706SJuan Quintela error_setg(errp, "Postcopy is not compatible with ignore-shared"); 32377608706SJuan Quintela return false; 32477608706SJuan Quintela } 325*b405dfffSLeonardo Bras 326*b405dfffSLeonardo Bras if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) { 327*b405dfffSLeonardo Bras error_setg(errp, "Postcopy is not yet compatible with multifd"); 328*b405dfffSLeonardo Bras return false; 329*b405dfffSLeonardo Bras } 33077608706SJuan Quintela } 33177608706SJuan Quintela 33277608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT]) { 33377608706SJuan Quintela WriteTrackingSupport wt_support; 33477608706SJuan Quintela int idx; 33577608706SJuan Quintela /* 33677608706SJuan Quintela * Check if 'background-snapshot' capability is supported by 33777608706SJuan Quintela * host kernel and compatible with guest memory configuration. 33877608706SJuan Quintela */ 33977608706SJuan Quintela wt_support = migrate_query_write_tracking(); 34077608706SJuan Quintela if (wt_support < WT_SUPPORT_AVAILABLE) { 34177608706SJuan Quintela error_setg(errp, "Background-snapshot is not supported by host kernel"); 34277608706SJuan Quintela return false; 34377608706SJuan Quintela } 34477608706SJuan Quintela if (wt_support < WT_SUPPORT_COMPATIBLE) { 34577608706SJuan Quintela error_setg(errp, "Background-snapshot is not compatible " 34677608706SJuan Quintela "with guest memory configuration"); 34777608706SJuan Quintela return false; 34877608706SJuan Quintela } 34977608706SJuan Quintela 35077608706SJuan Quintela /* 35177608706SJuan Quintela * Check if there are any migration capabilities 35277608706SJuan Quintela * incompatible with 'background-snapshot'. 35377608706SJuan Quintela */ 35477608706SJuan Quintela for (idx = 0; idx < check_caps_background_snapshot.size; idx++) { 35577608706SJuan Quintela int incomp_cap = check_caps_background_snapshot.caps[idx]; 35677608706SJuan Quintela if (new_caps[incomp_cap]) { 35777608706SJuan Quintela error_setg(errp, 35877608706SJuan Quintela "Background-snapshot is not compatible with %s", 35977608706SJuan Quintela MigrationCapability_str(incomp_cap)); 36077608706SJuan Quintela return false; 36177608706SJuan Quintela } 36277608706SJuan Quintela } 36377608706SJuan Quintela } 36477608706SJuan Quintela 36577608706SJuan Quintela #ifdef CONFIG_LINUX 36677608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND] && 36777608706SJuan Quintela (!new_caps[MIGRATION_CAPABILITY_MULTIFD] || 36877608706SJuan Quintela new_caps[MIGRATION_CAPABILITY_COMPRESS] || 36977608706SJuan Quintela new_caps[MIGRATION_CAPABILITY_XBZRLE] || 37077608706SJuan Quintela migrate_multifd_compression() || 37177608706SJuan Quintela migrate_use_tls())) { 37277608706SJuan Quintela error_setg(errp, 37377608706SJuan Quintela "Zero copy only available for non-compressed non-TLS multifd migration"); 37477608706SJuan Quintela return false; 37577608706SJuan Quintela } 37677608706SJuan Quintela #else 37777608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND]) { 37877608706SJuan Quintela error_setg(errp, 37977608706SJuan Quintela "Zero copy currently only available on Linux"); 38077608706SJuan Quintela return false; 38177608706SJuan Quintela } 38277608706SJuan Quintela #endif 38377608706SJuan Quintela 38477608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT]) { 38577608706SJuan Quintela if (!new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) { 38677608706SJuan Quintela error_setg(errp, "Postcopy preempt requires postcopy-ram"); 38777608706SJuan Quintela return false; 38877608706SJuan Quintela } 38977608706SJuan Quintela 39077608706SJuan Quintela /* 39177608706SJuan Quintela * Preempt mode requires urgent pages to be sent in separate 39277608706SJuan Quintela * channel, OTOH compression logic will disorder all pages into 39377608706SJuan Quintela * different compression channels, which is not compatible with the 39477608706SJuan Quintela * preempt assumptions on channel assignments. 39577608706SJuan Quintela */ 39677608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) { 39777608706SJuan Quintela error_setg(errp, "Postcopy preempt not compatible with compress"); 39877608706SJuan Quintela return false; 39977608706SJuan Quintela } 40077608706SJuan Quintela } 40177608706SJuan Quintela 40277608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) { 40377608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) { 40477608706SJuan Quintela error_setg(errp, "Multifd is not compatible with compress"); 40577608706SJuan Quintela return false; 40677608706SJuan Quintela } 40777608706SJuan Quintela } 40877608706SJuan Quintela 40977608706SJuan Quintela return true; 41077608706SJuan Quintela } 4114d0c6b69SJuan Quintela 412f80196b7SJuan Quintela bool migrate_cap_set(int cap, bool value, Error **errp) 413f80196b7SJuan Quintela { 414f80196b7SJuan Quintela MigrationState *s = migrate_get_current(); 415f80196b7SJuan Quintela bool new_caps[MIGRATION_CAPABILITY__MAX]; 416f80196b7SJuan Quintela 417f80196b7SJuan Quintela if (migration_is_running(s->state)) { 418f80196b7SJuan Quintela error_setg(errp, QERR_MIGRATION_ACTIVE); 419f80196b7SJuan Quintela return false; 420f80196b7SJuan Quintela } 421f80196b7SJuan Quintela 422f80196b7SJuan Quintela memcpy(new_caps, s->capabilities, sizeof(new_caps)); 423f80196b7SJuan Quintela new_caps[cap] = value; 424f80196b7SJuan Quintela 425f80196b7SJuan Quintela if (!migrate_caps_check(s->capabilities, new_caps, errp)) { 426f80196b7SJuan Quintela return false; 427f80196b7SJuan Quintela } 428f80196b7SJuan Quintela s->capabilities[cap] = value; 429f80196b7SJuan Quintela return true; 430f80196b7SJuan Quintela } 431f80196b7SJuan Quintela 4324d0c6b69SJuan Quintela MigrationCapabilityStatusList *qmp_query_migrate_capabilities(Error **errp) 4334d0c6b69SJuan Quintela { 4344d0c6b69SJuan Quintela MigrationCapabilityStatusList *head = NULL, **tail = &head; 4354d0c6b69SJuan Quintela MigrationCapabilityStatus *caps; 4364d0c6b69SJuan Quintela MigrationState *s = migrate_get_current(); 4374d0c6b69SJuan Quintela int i; 4384d0c6b69SJuan Quintela 4394d0c6b69SJuan Quintela for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) { 4404d0c6b69SJuan Quintela #ifndef CONFIG_LIVE_BLOCK_MIGRATION 4414d0c6b69SJuan Quintela if (i == MIGRATION_CAPABILITY_BLOCK) { 4424d0c6b69SJuan Quintela continue; 4434d0c6b69SJuan Quintela } 4444d0c6b69SJuan Quintela #endif 4454d0c6b69SJuan Quintela caps = g_malloc0(sizeof(*caps)); 4464d0c6b69SJuan Quintela caps->capability = i; 4474d0c6b69SJuan Quintela caps->state = s->capabilities[i]; 4484d0c6b69SJuan Quintela QAPI_LIST_APPEND(tail, caps); 4494d0c6b69SJuan Quintela } 4504d0c6b69SJuan Quintela 4514d0c6b69SJuan Quintela return head; 4524d0c6b69SJuan Quintela } 45345c1de13SJuan Quintela 45445c1de13SJuan Quintela void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params, 45545c1de13SJuan Quintela Error **errp) 45645c1de13SJuan Quintela { 45745c1de13SJuan Quintela MigrationState *s = migrate_get_current(); 45845c1de13SJuan Quintela MigrationCapabilityStatusList *cap; 45945c1de13SJuan Quintela bool new_caps[MIGRATION_CAPABILITY__MAX]; 46045c1de13SJuan Quintela 46145c1de13SJuan Quintela if (migration_is_running(s->state)) { 46245c1de13SJuan Quintela error_setg(errp, QERR_MIGRATION_ACTIVE); 46345c1de13SJuan Quintela return; 46445c1de13SJuan Quintela } 46545c1de13SJuan Quintela 46645c1de13SJuan Quintela memcpy(new_caps, s->capabilities, sizeof(new_caps)); 46745c1de13SJuan Quintela for (cap = params; cap; cap = cap->next) { 46845c1de13SJuan Quintela new_caps[cap->value->capability] = cap->value->state; 46945c1de13SJuan Quintela } 47045c1de13SJuan Quintela 47145c1de13SJuan Quintela if (!migrate_caps_check(s->capabilities, new_caps, errp)) { 47245c1de13SJuan Quintela return; 47345c1de13SJuan Quintela } 47445c1de13SJuan Quintela 47545c1de13SJuan Quintela for (cap = params; cap; cap = cap->next) { 47645c1de13SJuan Quintela s->capabilities[cap->value->capability] = cap->value->state; 47745c1de13SJuan Quintela } 47845c1de13SJuan Quintela } 4791dfc4b9eSJuan Quintela 4801dfc4b9eSJuan Quintela /* parameters */ 4811dfc4b9eSJuan Quintela 4826f8be708SJuan Quintela bool migrate_block_incremental(void) 4836f8be708SJuan Quintela { 4846f8be708SJuan Quintela MigrationState *s; 4856f8be708SJuan Quintela 4866f8be708SJuan Quintela s = migrate_get_current(); 4876f8be708SJuan Quintela 4886f8be708SJuan Quintela return s->parameters.block_incremental; 4896f8be708SJuan Quintela } 4906f8be708SJuan Quintela 491f94a858fSJuan Quintela uint32_t migrate_checkpoint_delay(void) 492f94a858fSJuan Quintela { 493f94a858fSJuan Quintela MigrationState *s; 494f94a858fSJuan Quintela 495f94a858fSJuan Quintela s = migrate_get_current(); 496f94a858fSJuan Quintela 497f94a858fSJuan Quintela return s->parameters.x_checkpoint_delay; 498f94a858fSJuan Quintela } 499f94a858fSJuan Quintela 5001dfc4b9eSJuan Quintela int migrate_compress_level(void) 5011dfc4b9eSJuan Quintela { 5021dfc4b9eSJuan Quintela MigrationState *s; 5031dfc4b9eSJuan Quintela 5041dfc4b9eSJuan Quintela s = migrate_get_current(); 5051dfc4b9eSJuan Quintela 5061dfc4b9eSJuan Quintela return s->parameters.compress_level; 5071dfc4b9eSJuan Quintela } 5081dfc4b9eSJuan Quintela 5091dfc4b9eSJuan Quintela int migrate_compress_threads(void) 5101dfc4b9eSJuan Quintela { 5111dfc4b9eSJuan Quintela MigrationState *s; 5121dfc4b9eSJuan Quintela 5131dfc4b9eSJuan Quintela s = migrate_get_current(); 5141dfc4b9eSJuan Quintela 5151dfc4b9eSJuan Quintela return s->parameters.compress_threads; 5161dfc4b9eSJuan Quintela } 5171dfc4b9eSJuan Quintela 5181dfc4b9eSJuan Quintela int migrate_compress_wait_thread(void) 5191dfc4b9eSJuan Quintela { 5201dfc4b9eSJuan Quintela MigrationState *s; 5211dfc4b9eSJuan Quintela 5221dfc4b9eSJuan Quintela s = migrate_get_current(); 5231dfc4b9eSJuan Quintela 5241dfc4b9eSJuan Quintela return s->parameters.compress_wait_thread; 5251dfc4b9eSJuan Quintela } 5261dfc4b9eSJuan Quintela 5279605c2acSJuan Quintela uint8_t migrate_cpu_throttle_increment(void) 5289605c2acSJuan Quintela { 5299605c2acSJuan Quintela MigrationState *s; 5309605c2acSJuan Quintela 5319605c2acSJuan Quintela s = migrate_get_current(); 5329605c2acSJuan Quintela 5339605c2acSJuan Quintela return s->parameters.cpu_throttle_increment; 5349605c2acSJuan Quintela } 5359605c2acSJuan Quintela 5362a8ec380SJuan Quintela uint8_t migrate_cpu_throttle_initial(void) 5372a8ec380SJuan Quintela { 5382a8ec380SJuan Quintela MigrationState *s; 5392a8ec380SJuan Quintela 5402a8ec380SJuan Quintela s = migrate_get_current(); 5412a8ec380SJuan Quintela 5422a8ec380SJuan Quintela return s->parameters.cpu_throttle_initial; 5432a8ec380SJuan Quintela } 5442a8ec380SJuan Quintela 545873f674cSJuan Quintela bool migrate_cpu_throttle_tailslow(void) 546873f674cSJuan Quintela { 547873f674cSJuan Quintela MigrationState *s; 548873f674cSJuan Quintela 549873f674cSJuan Quintela s = migrate_get_current(); 550873f674cSJuan Quintela 551873f674cSJuan Quintela return s->parameters.cpu_throttle_tailslow; 552873f674cSJuan Quintela } 553873f674cSJuan Quintela 5541dfc4b9eSJuan Quintela int migrate_decompress_threads(void) 5551dfc4b9eSJuan Quintela { 5561dfc4b9eSJuan Quintela MigrationState *s; 5571dfc4b9eSJuan Quintela 5581dfc4b9eSJuan Quintela s = migrate_get_current(); 5591dfc4b9eSJuan Quintela 5601dfc4b9eSJuan Quintela return s->parameters.decompress_threads; 5611dfc4b9eSJuan Quintela } 5621dfc4b9eSJuan Quintela 56324155bd0SJuan Quintela uint8_t migrate_max_cpu_throttle(void) 56424155bd0SJuan Quintela { 56524155bd0SJuan Quintela MigrationState *s; 56624155bd0SJuan Quintela 56724155bd0SJuan Quintela s = migrate_get_current(); 56824155bd0SJuan Quintela 56924155bd0SJuan Quintela return s->parameters.max_cpu_throttle; 57024155bd0SJuan Quintela } 57124155bd0SJuan Quintela 5729c894df3SJuan Quintela uint64_t migrate_max_bandwidth(void) 5739c894df3SJuan Quintela { 5749c894df3SJuan Quintela MigrationState *s; 5759c894df3SJuan Quintela 5769c894df3SJuan Quintela s = migrate_get_current(); 5779c894df3SJuan Quintela 5789c894df3SJuan Quintela return s->parameters.max_bandwidth; 5799c894df3SJuan Quintela } 5809c894df3SJuan Quintela 5811dfc4b9eSJuan Quintela int64_t migrate_max_postcopy_bandwidth(void) 5821dfc4b9eSJuan Quintela { 5831dfc4b9eSJuan Quintela MigrationState *s; 5841dfc4b9eSJuan Quintela 5851dfc4b9eSJuan Quintela s = migrate_get_current(); 5861dfc4b9eSJuan Quintela 5871dfc4b9eSJuan Quintela return s->parameters.max_postcopy_bandwidth; 5881dfc4b9eSJuan Quintela } 5891dfc4b9eSJuan Quintela 5901dfc4b9eSJuan Quintela int migrate_multifd_channels(void) 5911dfc4b9eSJuan Quintela { 5921dfc4b9eSJuan Quintela MigrationState *s; 5931dfc4b9eSJuan Quintela 5941dfc4b9eSJuan Quintela s = migrate_get_current(); 5951dfc4b9eSJuan Quintela 5961dfc4b9eSJuan Quintela return s->parameters.multifd_channels; 5971dfc4b9eSJuan Quintela } 5981dfc4b9eSJuan Quintela 5991dfc4b9eSJuan Quintela MultiFDCompression migrate_multifd_compression(void) 6001dfc4b9eSJuan Quintela { 6011dfc4b9eSJuan Quintela MigrationState *s; 6021dfc4b9eSJuan Quintela 6031dfc4b9eSJuan Quintela s = migrate_get_current(); 6041dfc4b9eSJuan Quintela 6051dfc4b9eSJuan Quintela assert(s->parameters.multifd_compression < MULTIFD_COMPRESSION__MAX); 6061dfc4b9eSJuan Quintela return s->parameters.multifd_compression; 6071dfc4b9eSJuan Quintela } 6081dfc4b9eSJuan Quintela 6091dfc4b9eSJuan Quintela int migrate_multifd_zlib_level(void) 6101dfc4b9eSJuan Quintela { 6111dfc4b9eSJuan Quintela MigrationState *s; 6121dfc4b9eSJuan Quintela 6131dfc4b9eSJuan Quintela s = migrate_get_current(); 6141dfc4b9eSJuan Quintela 6151dfc4b9eSJuan Quintela return s->parameters.multifd_zlib_level; 6161dfc4b9eSJuan Quintela } 6171dfc4b9eSJuan Quintela 6181dfc4b9eSJuan Quintela int migrate_multifd_zstd_level(void) 6191dfc4b9eSJuan Quintela { 6201dfc4b9eSJuan Quintela MigrationState *s; 6211dfc4b9eSJuan Quintela 6221dfc4b9eSJuan Quintela s = migrate_get_current(); 6231dfc4b9eSJuan Quintela 6241dfc4b9eSJuan Quintela return s->parameters.multifd_zstd_level; 6251dfc4b9eSJuan Quintela } 6261dfc4b9eSJuan Quintela 6276499efdbSJuan Quintela uint8_t migrate_throttle_trigger_threshold(void) 6286499efdbSJuan Quintela { 6296499efdbSJuan Quintela MigrationState *s; 6306499efdbSJuan Quintela 6316499efdbSJuan Quintela s = migrate_get_current(); 6326499efdbSJuan Quintela 6336499efdbSJuan Quintela return s->parameters.throttle_trigger_threshold; 6346499efdbSJuan Quintela } 6356499efdbSJuan Quintela 6361dfc4b9eSJuan Quintela uint64_t migrate_xbzrle_cache_size(void) 6371dfc4b9eSJuan Quintela { 6381dfc4b9eSJuan Quintela MigrationState *s; 6391dfc4b9eSJuan Quintela 6401dfc4b9eSJuan Quintela s = migrate_get_current(); 6411dfc4b9eSJuan Quintela 6421dfc4b9eSJuan Quintela return s->parameters.xbzrle_cache_size; 6431dfc4b9eSJuan Quintela } 6442682c4eeSJuan Quintela 6452682c4eeSJuan Quintela /* parameters helpers */ 6462682c4eeSJuan Quintela 6472682c4eeSJuan Quintela AnnounceParameters *migrate_announce_params(void) 6482682c4eeSJuan Quintela { 6492682c4eeSJuan Quintela static AnnounceParameters ap; 6502682c4eeSJuan Quintela 6512682c4eeSJuan Quintela MigrationState *s = migrate_get_current(); 6522682c4eeSJuan Quintela 6532682c4eeSJuan Quintela ap.initial = s->parameters.announce_initial; 6542682c4eeSJuan Quintela ap.max = s->parameters.announce_max; 6552682c4eeSJuan Quintela ap.rounds = s->parameters.announce_rounds; 6562682c4eeSJuan Quintela ap.step = s->parameters.announce_step; 6572682c4eeSJuan Quintela 6582682c4eeSJuan Quintela return ≈ 6592682c4eeSJuan Quintela } 6609c894df3SJuan Quintela 6619c894df3SJuan Quintela MigrationParameters *qmp_query_migrate_parameters(Error **errp) 6629c894df3SJuan Quintela { 6639c894df3SJuan Quintela MigrationParameters *params; 6649c894df3SJuan Quintela MigrationState *s = migrate_get_current(); 6659c894df3SJuan Quintela 6669c894df3SJuan Quintela /* TODO use QAPI_CLONE() instead of duplicating it inline */ 6679c894df3SJuan Quintela params = g_malloc0(sizeof(*params)); 6689c894df3SJuan Quintela params->has_compress_level = true; 6699c894df3SJuan Quintela params->compress_level = s->parameters.compress_level; 6709c894df3SJuan Quintela params->has_compress_threads = true; 6719c894df3SJuan Quintela params->compress_threads = s->parameters.compress_threads; 6729c894df3SJuan Quintela params->has_compress_wait_thread = true; 6739c894df3SJuan Quintela params->compress_wait_thread = s->parameters.compress_wait_thread; 6749c894df3SJuan Quintela params->has_decompress_threads = true; 6759c894df3SJuan Quintela params->decompress_threads = s->parameters.decompress_threads; 6769c894df3SJuan Quintela params->has_throttle_trigger_threshold = true; 6779c894df3SJuan Quintela params->throttle_trigger_threshold = s->parameters.throttle_trigger_threshold; 6789c894df3SJuan Quintela params->has_cpu_throttle_initial = true; 6799c894df3SJuan Quintela params->cpu_throttle_initial = s->parameters.cpu_throttle_initial; 6809c894df3SJuan Quintela params->has_cpu_throttle_increment = true; 6819c894df3SJuan Quintela params->cpu_throttle_increment = s->parameters.cpu_throttle_increment; 6829c894df3SJuan Quintela params->has_cpu_throttle_tailslow = true; 6839c894df3SJuan Quintela params->cpu_throttle_tailslow = s->parameters.cpu_throttle_tailslow; 6849c894df3SJuan Quintela params->tls_creds = g_strdup(s->parameters.tls_creds); 6859c894df3SJuan Quintela params->tls_hostname = g_strdup(s->parameters.tls_hostname); 6869c894df3SJuan Quintela params->tls_authz = g_strdup(s->parameters.tls_authz ? 6879c894df3SJuan Quintela s->parameters.tls_authz : ""); 6889c894df3SJuan Quintela params->has_max_bandwidth = true; 6899c894df3SJuan Quintela params->max_bandwidth = s->parameters.max_bandwidth; 6909c894df3SJuan Quintela params->has_downtime_limit = true; 6919c894df3SJuan Quintela params->downtime_limit = s->parameters.downtime_limit; 6929c894df3SJuan Quintela params->has_x_checkpoint_delay = true; 6939c894df3SJuan Quintela params->x_checkpoint_delay = s->parameters.x_checkpoint_delay; 6949c894df3SJuan Quintela params->has_block_incremental = true; 6959c894df3SJuan Quintela params->block_incremental = s->parameters.block_incremental; 6969c894df3SJuan Quintela params->has_multifd_channels = true; 6979c894df3SJuan Quintela params->multifd_channels = s->parameters.multifd_channels; 6989c894df3SJuan Quintela params->has_multifd_compression = true; 6999c894df3SJuan Quintela params->multifd_compression = s->parameters.multifd_compression; 7009c894df3SJuan Quintela params->has_multifd_zlib_level = true; 7019c894df3SJuan Quintela params->multifd_zlib_level = s->parameters.multifd_zlib_level; 7029c894df3SJuan Quintela params->has_multifd_zstd_level = true; 7039c894df3SJuan Quintela params->multifd_zstd_level = s->parameters.multifd_zstd_level; 7049c894df3SJuan Quintela params->has_xbzrle_cache_size = true; 7059c894df3SJuan Quintela params->xbzrle_cache_size = s->parameters.xbzrle_cache_size; 7069c894df3SJuan Quintela params->has_max_postcopy_bandwidth = true; 7079c894df3SJuan Quintela params->max_postcopy_bandwidth = s->parameters.max_postcopy_bandwidth; 7089c894df3SJuan Quintela params->has_max_cpu_throttle = true; 7099c894df3SJuan Quintela params->max_cpu_throttle = s->parameters.max_cpu_throttle; 7109c894df3SJuan Quintela params->has_announce_initial = true; 7119c894df3SJuan Quintela params->announce_initial = s->parameters.announce_initial; 7129c894df3SJuan Quintela params->has_announce_max = true; 7139c894df3SJuan Quintela params->announce_max = s->parameters.announce_max; 7149c894df3SJuan Quintela params->has_announce_rounds = true; 7159c894df3SJuan Quintela params->announce_rounds = s->parameters.announce_rounds; 7169c894df3SJuan Quintela params->has_announce_step = true; 7179c894df3SJuan Quintela params->announce_step = s->parameters.announce_step; 7189c894df3SJuan Quintela 7199c894df3SJuan Quintela if (s->parameters.has_block_bitmap_mapping) { 7209c894df3SJuan Quintela params->has_block_bitmap_mapping = true; 7219c894df3SJuan Quintela params->block_bitmap_mapping = 7229c894df3SJuan Quintela QAPI_CLONE(BitmapMigrationNodeAliasList, 7239c894df3SJuan Quintela s->parameters.block_bitmap_mapping); 7249c894df3SJuan Quintela } 7259c894df3SJuan Quintela 7269c894df3SJuan Quintela return params; 7279c894df3SJuan Quintela } 728