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" 1577608706SJuan Quintela #include "qapi/error.h" 164d0c6b69SJuan Quintela #include "qapi/qapi-commands-migration.h" 17f80196b7SJuan Quintela #include "qapi/qmp/qerror.h" 1877608706SJuan Quintela #include "sysemu/runstate.h" 19*2682c4eeSJuan Quintela #include "migration/misc.h" 201f0776f1SJuan Quintela #include "migration.h" 2177608706SJuan Quintela #include "ram.h" 221f0776f1SJuan Quintela #include "options.h" 231f0776f1SJuan Quintela 241f0776f1SJuan Quintela bool migrate_auto_converge(void) 251f0776f1SJuan Quintela { 261f0776f1SJuan Quintela MigrationState *s; 271f0776f1SJuan Quintela 281f0776f1SJuan Quintela s = migrate_get_current(); 291f0776f1SJuan Quintela 301f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_AUTO_CONVERGE]; 311f0776f1SJuan Quintela } 321f0776f1SJuan Quintela 331f0776f1SJuan Quintela bool migrate_background_snapshot(void) 341f0776f1SJuan Quintela { 351f0776f1SJuan Quintela MigrationState *s; 361f0776f1SJuan Quintela 371f0776f1SJuan Quintela s = migrate_get_current(); 381f0776f1SJuan Quintela 391f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT]; 401f0776f1SJuan Quintela } 411f0776f1SJuan Quintela 429d4b1e5fSJuan Quintela bool migrate_block(void) 439d4b1e5fSJuan Quintela { 449d4b1e5fSJuan Quintela MigrationState *s; 459d4b1e5fSJuan Quintela 469d4b1e5fSJuan Quintela s = migrate_get_current(); 479d4b1e5fSJuan Quintela 489d4b1e5fSJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_BLOCK]; 499d4b1e5fSJuan Quintela } 509d4b1e5fSJuan Quintela 515e804644SJuan Quintela bool migrate_colo(void) 525e804644SJuan Quintela { 535e804644SJuan Quintela MigrationState *s = migrate_get_current(); 545e804644SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_X_COLO]; 555e804644SJuan Quintela } 565e804644SJuan Quintela 57a7a94d14SJuan Quintela bool migrate_compress(void) 58a7a94d14SJuan Quintela { 59a7a94d14SJuan Quintela MigrationState *s; 60a7a94d14SJuan Quintela 61a7a94d14SJuan Quintela s = migrate_get_current(); 62a7a94d14SJuan Quintela 63a7a94d14SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_COMPRESS]; 64a7a94d14SJuan Quintela } 65a7a94d14SJuan Quintela 661f0776f1SJuan Quintela bool migrate_dirty_bitmaps(void) 671f0776f1SJuan Quintela { 681f0776f1SJuan Quintela MigrationState *s; 691f0776f1SJuan Quintela 701f0776f1SJuan Quintela s = migrate_get_current(); 711f0776f1SJuan Quintela 721f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_DIRTY_BITMAPS]; 731f0776f1SJuan Quintela } 741f0776f1SJuan Quintela 75b890902cSJuan Quintela bool migrate_events(void) 76b890902cSJuan Quintela { 77b890902cSJuan Quintela MigrationState *s; 78b890902cSJuan Quintela 79b890902cSJuan Quintela s = migrate_get_current(); 80b890902cSJuan Quintela 81b890902cSJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_EVENTS]; 82b890902cSJuan Quintela } 83b890902cSJuan Quintela 841f0776f1SJuan Quintela bool migrate_ignore_shared(void) 851f0776f1SJuan Quintela { 861f0776f1SJuan Quintela MigrationState *s; 871f0776f1SJuan Quintela 881f0776f1SJuan Quintela s = migrate_get_current(); 891f0776f1SJuan Quintela 901f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_X_IGNORE_SHARED]; 911f0776f1SJuan Quintela } 921f0776f1SJuan Quintela 931f0776f1SJuan Quintela bool migrate_late_block_activate(void) 941f0776f1SJuan Quintela { 951f0776f1SJuan Quintela MigrationState *s; 961f0776f1SJuan Quintela 971f0776f1SJuan Quintela s = migrate_get_current(); 981f0776f1SJuan Quintela 991f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE]; 1001f0776f1SJuan Quintela } 1011f0776f1SJuan Quintela 10251b07548SJuan Quintela bool migrate_multifd(void) 10351b07548SJuan Quintela { 10451b07548SJuan Quintela MigrationState *s; 10551b07548SJuan Quintela 10651b07548SJuan Quintela s = migrate_get_current(); 10751b07548SJuan Quintela 10851b07548SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_MULTIFD]; 10951b07548SJuan Quintela } 11051b07548SJuan Quintela 1111f0776f1SJuan Quintela bool migrate_pause_before_switchover(void) 1121f0776f1SJuan Quintela { 1131f0776f1SJuan Quintela MigrationState *s; 1141f0776f1SJuan Quintela 1151f0776f1SJuan Quintela s = migrate_get_current(); 1161f0776f1SJuan Quintela 1171f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER]; 1181f0776f1SJuan Quintela } 1191f0776f1SJuan Quintela 1201f0776f1SJuan Quintela bool migrate_postcopy_blocktime(void) 1211f0776f1SJuan Quintela { 1221f0776f1SJuan Quintela MigrationState *s; 1231f0776f1SJuan Quintela 1241f0776f1SJuan Quintela s = migrate_get_current(); 1251f0776f1SJuan Quintela 1261f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME]; 1271f0776f1SJuan Quintela } 1281f0776f1SJuan Quintela 1291f0776f1SJuan Quintela bool migrate_postcopy_preempt(void) 1301f0776f1SJuan Quintela { 1311f0776f1SJuan Quintela MigrationState *s; 1321f0776f1SJuan Quintela 1331f0776f1SJuan Quintela s = migrate_get_current(); 1341f0776f1SJuan Quintela 1351f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT]; 1361f0776f1SJuan Quintela } 1371f0776f1SJuan Quintela 1381f0776f1SJuan Quintela bool migrate_postcopy_ram(void) 1391f0776f1SJuan Quintela { 1401f0776f1SJuan Quintela MigrationState *s; 1411f0776f1SJuan Quintela 1421f0776f1SJuan Quintela s = migrate_get_current(); 1431f0776f1SJuan Quintela 1441f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_RAM]; 1451f0776f1SJuan Quintela } 1461f0776f1SJuan Quintela 14717cba690SJuan Quintela bool migrate_rdma_pin_all(void) 14817cba690SJuan Quintela { 14917cba690SJuan Quintela MigrationState *s = migrate_get_current(); 15017cba690SJuan Quintela 15117cba690SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_RDMA_PIN_ALL]; 15217cba690SJuan Quintela } 15317cba690SJuan Quintela 1541f0776f1SJuan Quintela bool migrate_release_ram(void) 1551f0776f1SJuan Quintela { 1561f0776f1SJuan Quintela MigrationState *s; 1571f0776f1SJuan Quintela 1581f0776f1SJuan Quintela s = migrate_get_current(); 1591f0776f1SJuan Quintela 1601f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_RELEASE_RAM]; 1611f0776f1SJuan Quintela } 1621f0776f1SJuan Quintela 16338ad1110SJuan Quintela bool migrate_return_path(void) 16438ad1110SJuan Quintela { 16538ad1110SJuan Quintela MigrationState *s; 16638ad1110SJuan Quintela 16738ad1110SJuan Quintela s = migrate_get_current(); 16838ad1110SJuan Quintela 16938ad1110SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_RETURN_PATH]; 17038ad1110SJuan Quintela } 17138ad1110SJuan Quintela 1721f0776f1SJuan Quintela bool migrate_validate_uuid(void) 1731f0776f1SJuan Quintela { 1741f0776f1SJuan Quintela MigrationState *s; 1751f0776f1SJuan Quintela 1761f0776f1SJuan Quintela s = migrate_get_current(); 1771f0776f1SJuan Quintela 1781f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_VALIDATE_UUID]; 1791f0776f1SJuan Quintela } 1801f0776f1SJuan Quintela 18187dca0c9SJuan Quintela bool migrate_xbzrle(void) 18287dca0c9SJuan Quintela { 18387dca0c9SJuan Quintela MigrationState *s; 18487dca0c9SJuan Quintela 18587dca0c9SJuan Quintela s = migrate_get_current(); 18687dca0c9SJuan Quintela 18787dca0c9SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_XBZRLE]; 18887dca0c9SJuan Quintela } 18987dca0c9SJuan Quintela 1901f0776f1SJuan Quintela bool migrate_zero_blocks(void) 1911f0776f1SJuan Quintela { 1921f0776f1SJuan Quintela MigrationState *s; 1931f0776f1SJuan Quintela 1941f0776f1SJuan Quintela s = migrate_get_current(); 1951f0776f1SJuan Quintela 1961f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_ZERO_BLOCKS]; 1971f0776f1SJuan Quintela } 198b4bc342cSJuan Quintela 199b4bc342cSJuan Quintela bool migrate_zero_copy_send(void) 200b4bc342cSJuan Quintela { 201b4bc342cSJuan Quintela MigrationState *s; 202b4bc342cSJuan Quintela 203b4bc342cSJuan Quintela s = migrate_get_current(); 204b4bc342cSJuan Quintela 205b4bc342cSJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_ZERO_COPY_SEND]; 206b4bc342cSJuan Quintela } 20777608706SJuan Quintela typedef enum WriteTrackingSupport { 20877608706SJuan Quintela WT_SUPPORT_UNKNOWN = 0, 20977608706SJuan Quintela WT_SUPPORT_ABSENT, 21077608706SJuan Quintela WT_SUPPORT_AVAILABLE, 21177608706SJuan Quintela WT_SUPPORT_COMPATIBLE 21277608706SJuan Quintela } WriteTrackingSupport; 21377608706SJuan Quintela 21477608706SJuan Quintela static 21577608706SJuan Quintela WriteTrackingSupport migrate_query_write_tracking(void) 21677608706SJuan Quintela { 21777608706SJuan Quintela /* Check if kernel supports required UFFD features */ 21877608706SJuan Quintela if (!ram_write_tracking_available()) { 21977608706SJuan Quintela return WT_SUPPORT_ABSENT; 22077608706SJuan Quintela } 22177608706SJuan Quintela /* 22277608706SJuan Quintela * Check if current memory configuration is 22377608706SJuan Quintela * compatible with required UFFD features. 22477608706SJuan Quintela */ 22577608706SJuan Quintela if (!ram_write_tracking_compatible()) { 22677608706SJuan Quintela return WT_SUPPORT_AVAILABLE; 22777608706SJuan Quintela } 22877608706SJuan Quintela 22977608706SJuan Quintela return WT_SUPPORT_COMPATIBLE; 23077608706SJuan Quintela } 23177608706SJuan Quintela 23277608706SJuan Quintela /* Migration capabilities set */ 23377608706SJuan Quintela struct MigrateCapsSet { 23477608706SJuan Quintela int size; /* Capability set size */ 23577608706SJuan Quintela MigrationCapability caps[]; /* Variadic array of capabilities */ 23677608706SJuan Quintela }; 23777608706SJuan Quintela typedef struct MigrateCapsSet MigrateCapsSet; 23877608706SJuan Quintela 23977608706SJuan Quintela /* Define and initialize MigrateCapsSet */ 24077608706SJuan Quintela #define INITIALIZE_MIGRATE_CAPS_SET(_name, ...) \ 24177608706SJuan Quintela MigrateCapsSet _name = { \ 24277608706SJuan Quintela .size = sizeof((int []) { __VA_ARGS__ }) / sizeof(int), \ 24377608706SJuan Quintela .caps = { __VA_ARGS__ } \ 24477608706SJuan Quintela } 24577608706SJuan Quintela 24677608706SJuan Quintela /* Background-snapshot compatibility check list */ 24777608706SJuan Quintela static const 24877608706SJuan Quintela INITIALIZE_MIGRATE_CAPS_SET(check_caps_background_snapshot, 24977608706SJuan Quintela MIGRATION_CAPABILITY_POSTCOPY_RAM, 25077608706SJuan Quintela MIGRATION_CAPABILITY_DIRTY_BITMAPS, 25177608706SJuan Quintela MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME, 25277608706SJuan Quintela MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE, 25377608706SJuan Quintela MIGRATION_CAPABILITY_RETURN_PATH, 25477608706SJuan Quintela MIGRATION_CAPABILITY_MULTIFD, 25577608706SJuan Quintela MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER, 25677608706SJuan Quintela MIGRATION_CAPABILITY_AUTO_CONVERGE, 25777608706SJuan Quintela MIGRATION_CAPABILITY_RELEASE_RAM, 25877608706SJuan Quintela MIGRATION_CAPABILITY_RDMA_PIN_ALL, 25977608706SJuan Quintela MIGRATION_CAPABILITY_COMPRESS, 26077608706SJuan Quintela MIGRATION_CAPABILITY_XBZRLE, 26177608706SJuan Quintela MIGRATION_CAPABILITY_X_COLO, 26277608706SJuan Quintela MIGRATION_CAPABILITY_VALIDATE_UUID, 26377608706SJuan Quintela MIGRATION_CAPABILITY_ZERO_COPY_SEND); 26477608706SJuan Quintela 26577608706SJuan Quintela /** 26677608706SJuan Quintela * @migration_caps_check - check capability compatibility 26777608706SJuan Quintela * 26877608706SJuan Quintela * @old_caps: old capability list 26977608706SJuan Quintela * @new_caps: new capability list 27077608706SJuan Quintela * @errp: set *errp if the check failed, with reason 27177608706SJuan Quintela * 27277608706SJuan Quintela * Returns true if check passed, otherwise false. 27377608706SJuan Quintela */ 27477608706SJuan Quintela bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp) 27577608706SJuan Quintela { 27677608706SJuan Quintela MigrationIncomingState *mis = migration_incoming_get_current(); 27777608706SJuan Quintela 27877608706SJuan Quintela #ifndef CONFIG_LIVE_BLOCK_MIGRATION 27977608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_BLOCK]) { 28077608706SJuan Quintela error_setg(errp, "QEMU compiled without old-style (blk/-b, inc/-i) " 28177608706SJuan Quintela "block migration"); 28277608706SJuan Quintela error_append_hint(errp, "Use drive_mirror+NBD instead.\n"); 28377608706SJuan Quintela return false; 28477608706SJuan Quintela } 28577608706SJuan Quintela #endif 28677608706SJuan Quintela 28777608706SJuan Quintela #ifndef CONFIG_REPLICATION 28877608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_X_COLO]) { 28977608706SJuan Quintela error_setg(errp, "QEMU compiled without replication module" 29077608706SJuan Quintela " can't enable COLO"); 29177608706SJuan Quintela error_append_hint(errp, "Please enable replication before COLO.\n"); 29277608706SJuan Quintela return false; 29377608706SJuan Quintela } 29477608706SJuan Quintela #endif 29577608706SJuan Quintela 29677608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) { 29777608706SJuan Quintela /* This check is reasonably expensive, so only when it's being 29877608706SJuan Quintela * set the first time, also it's only the destination that needs 29977608706SJuan Quintela * special support. 30077608706SJuan Quintela */ 30177608706SJuan Quintela if (!old_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM] && 30277608706SJuan Quintela runstate_check(RUN_STATE_INMIGRATE) && 30377608706SJuan Quintela !postcopy_ram_supported_by_host(mis)) { 30477608706SJuan Quintela /* postcopy_ram_supported_by_host will have emitted a more 30577608706SJuan Quintela * detailed message 30677608706SJuan Quintela */ 30777608706SJuan Quintela error_setg(errp, "Postcopy is not supported"); 30877608706SJuan Quintela return false; 30977608706SJuan Quintela } 31077608706SJuan Quintela 31177608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_X_IGNORE_SHARED]) { 31277608706SJuan Quintela error_setg(errp, "Postcopy is not compatible with ignore-shared"); 31377608706SJuan Quintela return false; 31477608706SJuan Quintela } 31577608706SJuan Quintela } 31677608706SJuan Quintela 31777608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT]) { 31877608706SJuan Quintela WriteTrackingSupport wt_support; 31977608706SJuan Quintela int idx; 32077608706SJuan Quintela /* 32177608706SJuan Quintela * Check if 'background-snapshot' capability is supported by 32277608706SJuan Quintela * host kernel and compatible with guest memory configuration. 32377608706SJuan Quintela */ 32477608706SJuan Quintela wt_support = migrate_query_write_tracking(); 32577608706SJuan Quintela if (wt_support < WT_SUPPORT_AVAILABLE) { 32677608706SJuan Quintela error_setg(errp, "Background-snapshot is not supported by host kernel"); 32777608706SJuan Quintela return false; 32877608706SJuan Quintela } 32977608706SJuan Quintela if (wt_support < WT_SUPPORT_COMPATIBLE) { 33077608706SJuan Quintela error_setg(errp, "Background-snapshot is not compatible " 33177608706SJuan Quintela "with guest memory configuration"); 33277608706SJuan Quintela return false; 33377608706SJuan Quintela } 33477608706SJuan Quintela 33577608706SJuan Quintela /* 33677608706SJuan Quintela * Check if there are any migration capabilities 33777608706SJuan Quintela * incompatible with 'background-snapshot'. 33877608706SJuan Quintela */ 33977608706SJuan Quintela for (idx = 0; idx < check_caps_background_snapshot.size; idx++) { 34077608706SJuan Quintela int incomp_cap = check_caps_background_snapshot.caps[idx]; 34177608706SJuan Quintela if (new_caps[incomp_cap]) { 34277608706SJuan Quintela error_setg(errp, 34377608706SJuan Quintela "Background-snapshot is not compatible with %s", 34477608706SJuan Quintela MigrationCapability_str(incomp_cap)); 34577608706SJuan Quintela return false; 34677608706SJuan Quintela } 34777608706SJuan Quintela } 34877608706SJuan Quintela } 34977608706SJuan Quintela 35077608706SJuan Quintela #ifdef CONFIG_LINUX 35177608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND] && 35277608706SJuan Quintela (!new_caps[MIGRATION_CAPABILITY_MULTIFD] || 35377608706SJuan Quintela new_caps[MIGRATION_CAPABILITY_COMPRESS] || 35477608706SJuan Quintela new_caps[MIGRATION_CAPABILITY_XBZRLE] || 35577608706SJuan Quintela migrate_multifd_compression() || 35677608706SJuan Quintela migrate_use_tls())) { 35777608706SJuan Quintela error_setg(errp, 35877608706SJuan Quintela "Zero copy only available for non-compressed non-TLS multifd migration"); 35977608706SJuan Quintela return false; 36077608706SJuan Quintela } 36177608706SJuan Quintela #else 36277608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND]) { 36377608706SJuan Quintela error_setg(errp, 36477608706SJuan Quintela "Zero copy currently only available on Linux"); 36577608706SJuan Quintela return false; 36677608706SJuan Quintela } 36777608706SJuan Quintela #endif 36877608706SJuan Quintela 36977608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT]) { 37077608706SJuan Quintela if (!new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) { 37177608706SJuan Quintela error_setg(errp, "Postcopy preempt requires postcopy-ram"); 37277608706SJuan Quintela return false; 37377608706SJuan Quintela } 37477608706SJuan Quintela 37577608706SJuan Quintela /* 37677608706SJuan Quintela * Preempt mode requires urgent pages to be sent in separate 37777608706SJuan Quintela * channel, OTOH compression logic will disorder all pages into 37877608706SJuan Quintela * different compression channels, which is not compatible with the 37977608706SJuan Quintela * preempt assumptions on channel assignments. 38077608706SJuan Quintela */ 38177608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) { 38277608706SJuan Quintela error_setg(errp, "Postcopy preempt not compatible with compress"); 38377608706SJuan Quintela return false; 38477608706SJuan Quintela } 38577608706SJuan Quintela } 38677608706SJuan Quintela 38777608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) { 38877608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) { 38977608706SJuan Quintela error_setg(errp, "Multifd is not compatible with compress"); 39077608706SJuan Quintela return false; 39177608706SJuan Quintela } 39277608706SJuan Quintela } 39377608706SJuan Quintela 39477608706SJuan Quintela return true; 39577608706SJuan Quintela } 3964d0c6b69SJuan Quintela 397f80196b7SJuan Quintela bool migrate_cap_set(int cap, bool value, Error **errp) 398f80196b7SJuan Quintela { 399f80196b7SJuan Quintela MigrationState *s = migrate_get_current(); 400f80196b7SJuan Quintela bool new_caps[MIGRATION_CAPABILITY__MAX]; 401f80196b7SJuan Quintela 402f80196b7SJuan Quintela if (migration_is_running(s->state)) { 403f80196b7SJuan Quintela error_setg(errp, QERR_MIGRATION_ACTIVE); 404f80196b7SJuan Quintela return false; 405f80196b7SJuan Quintela } 406f80196b7SJuan Quintela 407f80196b7SJuan Quintela memcpy(new_caps, s->capabilities, sizeof(new_caps)); 408f80196b7SJuan Quintela new_caps[cap] = value; 409f80196b7SJuan Quintela 410f80196b7SJuan Quintela if (!migrate_caps_check(s->capabilities, new_caps, errp)) { 411f80196b7SJuan Quintela return false; 412f80196b7SJuan Quintela } 413f80196b7SJuan Quintela s->capabilities[cap] = value; 414f80196b7SJuan Quintela return true; 415f80196b7SJuan Quintela } 416f80196b7SJuan Quintela 4174d0c6b69SJuan Quintela MigrationCapabilityStatusList *qmp_query_migrate_capabilities(Error **errp) 4184d0c6b69SJuan Quintela { 4194d0c6b69SJuan Quintela MigrationCapabilityStatusList *head = NULL, **tail = &head; 4204d0c6b69SJuan Quintela MigrationCapabilityStatus *caps; 4214d0c6b69SJuan Quintela MigrationState *s = migrate_get_current(); 4224d0c6b69SJuan Quintela int i; 4234d0c6b69SJuan Quintela 4244d0c6b69SJuan Quintela for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) { 4254d0c6b69SJuan Quintela #ifndef CONFIG_LIVE_BLOCK_MIGRATION 4264d0c6b69SJuan Quintela if (i == MIGRATION_CAPABILITY_BLOCK) { 4274d0c6b69SJuan Quintela continue; 4284d0c6b69SJuan Quintela } 4294d0c6b69SJuan Quintela #endif 4304d0c6b69SJuan Quintela caps = g_malloc0(sizeof(*caps)); 4314d0c6b69SJuan Quintela caps->capability = i; 4324d0c6b69SJuan Quintela caps->state = s->capabilities[i]; 4334d0c6b69SJuan Quintela QAPI_LIST_APPEND(tail, caps); 4344d0c6b69SJuan Quintela } 4354d0c6b69SJuan Quintela 4364d0c6b69SJuan Quintela return head; 4374d0c6b69SJuan Quintela } 43845c1de13SJuan Quintela 43945c1de13SJuan Quintela void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params, 44045c1de13SJuan Quintela Error **errp) 44145c1de13SJuan Quintela { 44245c1de13SJuan Quintela MigrationState *s = migrate_get_current(); 44345c1de13SJuan Quintela MigrationCapabilityStatusList *cap; 44445c1de13SJuan Quintela bool new_caps[MIGRATION_CAPABILITY__MAX]; 44545c1de13SJuan Quintela 44645c1de13SJuan Quintela if (migration_is_running(s->state)) { 44745c1de13SJuan Quintela error_setg(errp, QERR_MIGRATION_ACTIVE); 44845c1de13SJuan Quintela return; 44945c1de13SJuan Quintela } 45045c1de13SJuan Quintela 45145c1de13SJuan Quintela memcpy(new_caps, s->capabilities, sizeof(new_caps)); 45245c1de13SJuan Quintela for (cap = params; cap; cap = cap->next) { 45345c1de13SJuan Quintela new_caps[cap->value->capability] = cap->value->state; 45445c1de13SJuan Quintela } 45545c1de13SJuan Quintela 45645c1de13SJuan Quintela if (!migrate_caps_check(s->capabilities, new_caps, errp)) { 45745c1de13SJuan Quintela return; 45845c1de13SJuan Quintela } 45945c1de13SJuan Quintela 46045c1de13SJuan Quintela for (cap = params; cap; cap = cap->next) { 46145c1de13SJuan Quintela s->capabilities[cap->value->capability] = cap->value->state; 46245c1de13SJuan Quintela } 46345c1de13SJuan Quintela } 4641dfc4b9eSJuan Quintela 4651dfc4b9eSJuan Quintela /* parameters */ 4661dfc4b9eSJuan Quintela 4676f8be708SJuan Quintela bool migrate_block_incremental(void) 4686f8be708SJuan Quintela { 4696f8be708SJuan Quintela MigrationState *s; 4706f8be708SJuan Quintela 4716f8be708SJuan Quintela s = migrate_get_current(); 4726f8be708SJuan Quintela 4736f8be708SJuan Quintela return s->parameters.block_incremental; 4746f8be708SJuan Quintela } 4756f8be708SJuan Quintela 476f94a858fSJuan Quintela uint32_t migrate_checkpoint_delay(void) 477f94a858fSJuan Quintela { 478f94a858fSJuan Quintela MigrationState *s; 479f94a858fSJuan Quintela 480f94a858fSJuan Quintela s = migrate_get_current(); 481f94a858fSJuan Quintela 482f94a858fSJuan Quintela return s->parameters.x_checkpoint_delay; 483f94a858fSJuan Quintela } 484f94a858fSJuan Quintela 4851dfc4b9eSJuan Quintela int migrate_compress_level(void) 4861dfc4b9eSJuan Quintela { 4871dfc4b9eSJuan Quintela MigrationState *s; 4881dfc4b9eSJuan Quintela 4891dfc4b9eSJuan Quintela s = migrate_get_current(); 4901dfc4b9eSJuan Quintela 4911dfc4b9eSJuan Quintela return s->parameters.compress_level; 4921dfc4b9eSJuan Quintela } 4931dfc4b9eSJuan Quintela 4941dfc4b9eSJuan Quintela int migrate_compress_threads(void) 4951dfc4b9eSJuan Quintela { 4961dfc4b9eSJuan Quintela MigrationState *s; 4971dfc4b9eSJuan Quintela 4981dfc4b9eSJuan Quintela s = migrate_get_current(); 4991dfc4b9eSJuan Quintela 5001dfc4b9eSJuan Quintela return s->parameters.compress_threads; 5011dfc4b9eSJuan Quintela } 5021dfc4b9eSJuan Quintela 5031dfc4b9eSJuan Quintela int migrate_compress_wait_thread(void) 5041dfc4b9eSJuan Quintela { 5051dfc4b9eSJuan Quintela MigrationState *s; 5061dfc4b9eSJuan Quintela 5071dfc4b9eSJuan Quintela s = migrate_get_current(); 5081dfc4b9eSJuan Quintela 5091dfc4b9eSJuan Quintela return s->parameters.compress_wait_thread; 5101dfc4b9eSJuan Quintela } 5111dfc4b9eSJuan Quintela 5121dfc4b9eSJuan Quintela int migrate_decompress_threads(void) 5131dfc4b9eSJuan Quintela { 5141dfc4b9eSJuan Quintela MigrationState *s; 5151dfc4b9eSJuan Quintela 5161dfc4b9eSJuan Quintela s = migrate_get_current(); 5171dfc4b9eSJuan Quintela 5181dfc4b9eSJuan Quintela return s->parameters.decompress_threads; 5191dfc4b9eSJuan Quintela } 5201dfc4b9eSJuan Quintela 52124155bd0SJuan Quintela uint8_t migrate_max_cpu_throttle(void) 52224155bd0SJuan Quintela { 52324155bd0SJuan Quintela MigrationState *s; 52424155bd0SJuan Quintela 52524155bd0SJuan Quintela s = migrate_get_current(); 52624155bd0SJuan Quintela 52724155bd0SJuan Quintela return s->parameters.max_cpu_throttle; 52824155bd0SJuan Quintela } 52924155bd0SJuan Quintela 5301dfc4b9eSJuan Quintela int64_t migrate_max_postcopy_bandwidth(void) 5311dfc4b9eSJuan Quintela { 5321dfc4b9eSJuan Quintela MigrationState *s; 5331dfc4b9eSJuan Quintela 5341dfc4b9eSJuan Quintela s = migrate_get_current(); 5351dfc4b9eSJuan Quintela 5361dfc4b9eSJuan Quintela return s->parameters.max_postcopy_bandwidth; 5371dfc4b9eSJuan Quintela } 5381dfc4b9eSJuan Quintela 5391dfc4b9eSJuan Quintela int migrate_multifd_channels(void) 5401dfc4b9eSJuan Quintela { 5411dfc4b9eSJuan Quintela MigrationState *s; 5421dfc4b9eSJuan Quintela 5431dfc4b9eSJuan Quintela s = migrate_get_current(); 5441dfc4b9eSJuan Quintela 5451dfc4b9eSJuan Quintela return s->parameters.multifd_channels; 5461dfc4b9eSJuan Quintela } 5471dfc4b9eSJuan Quintela 5481dfc4b9eSJuan Quintela MultiFDCompression migrate_multifd_compression(void) 5491dfc4b9eSJuan Quintela { 5501dfc4b9eSJuan Quintela MigrationState *s; 5511dfc4b9eSJuan Quintela 5521dfc4b9eSJuan Quintela s = migrate_get_current(); 5531dfc4b9eSJuan Quintela 5541dfc4b9eSJuan Quintela assert(s->parameters.multifd_compression < MULTIFD_COMPRESSION__MAX); 5551dfc4b9eSJuan Quintela return s->parameters.multifd_compression; 5561dfc4b9eSJuan Quintela } 5571dfc4b9eSJuan Quintela 5581dfc4b9eSJuan Quintela int migrate_multifd_zlib_level(void) 5591dfc4b9eSJuan Quintela { 5601dfc4b9eSJuan Quintela MigrationState *s; 5611dfc4b9eSJuan Quintela 5621dfc4b9eSJuan Quintela s = migrate_get_current(); 5631dfc4b9eSJuan Quintela 5641dfc4b9eSJuan Quintela return s->parameters.multifd_zlib_level; 5651dfc4b9eSJuan Quintela } 5661dfc4b9eSJuan Quintela 5671dfc4b9eSJuan Quintela int migrate_multifd_zstd_level(void) 5681dfc4b9eSJuan Quintela { 5691dfc4b9eSJuan Quintela MigrationState *s; 5701dfc4b9eSJuan Quintela 5711dfc4b9eSJuan Quintela s = migrate_get_current(); 5721dfc4b9eSJuan Quintela 5731dfc4b9eSJuan Quintela return s->parameters.multifd_zstd_level; 5741dfc4b9eSJuan Quintela } 5751dfc4b9eSJuan Quintela 5766499efdbSJuan Quintela uint8_t migrate_throttle_trigger_threshold(void) 5776499efdbSJuan Quintela { 5786499efdbSJuan Quintela MigrationState *s; 5796499efdbSJuan Quintela 5806499efdbSJuan Quintela s = migrate_get_current(); 5816499efdbSJuan Quintela 5826499efdbSJuan Quintela return s->parameters.throttle_trigger_threshold; 5836499efdbSJuan Quintela } 5846499efdbSJuan Quintela 5851dfc4b9eSJuan Quintela uint64_t migrate_xbzrle_cache_size(void) 5861dfc4b9eSJuan Quintela { 5871dfc4b9eSJuan Quintela MigrationState *s; 5881dfc4b9eSJuan Quintela 5891dfc4b9eSJuan Quintela s = migrate_get_current(); 5901dfc4b9eSJuan Quintela 5911dfc4b9eSJuan Quintela return s->parameters.xbzrle_cache_size; 5921dfc4b9eSJuan Quintela } 593*2682c4eeSJuan Quintela 594*2682c4eeSJuan Quintela /* parameters helpers */ 595*2682c4eeSJuan Quintela 596*2682c4eeSJuan Quintela AnnounceParameters *migrate_announce_params(void) 597*2682c4eeSJuan Quintela { 598*2682c4eeSJuan Quintela static AnnounceParameters ap; 599*2682c4eeSJuan Quintela 600*2682c4eeSJuan Quintela MigrationState *s = migrate_get_current(); 601*2682c4eeSJuan Quintela 602*2682c4eeSJuan Quintela ap.initial = s->parameters.announce_initial; 603*2682c4eeSJuan Quintela ap.max = s->parameters.announce_max; 604*2682c4eeSJuan Quintela ap.rounds = s->parameters.announce_rounds; 605*2682c4eeSJuan Quintela ap.step = s->parameters.announce_step; 606*2682c4eeSJuan Quintela 607*2682c4eeSJuan Quintela return ≈ 608*2682c4eeSJuan Quintela } 609