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" 17*f80196b7SJuan Quintela #include "qapi/qmp/qerror.h" 1877608706SJuan Quintela #include "sysemu/runstate.h" 191f0776f1SJuan Quintela #include "migration.h" 2077608706SJuan Quintela #include "ram.h" 211f0776f1SJuan Quintela #include "options.h" 221f0776f1SJuan Quintela 231f0776f1SJuan Quintela bool migrate_auto_converge(void) 241f0776f1SJuan Quintela { 251f0776f1SJuan Quintela MigrationState *s; 261f0776f1SJuan Quintela 271f0776f1SJuan Quintela s = migrate_get_current(); 281f0776f1SJuan Quintela 291f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_AUTO_CONVERGE]; 301f0776f1SJuan Quintela } 311f0776f1SJuan Quintela 321f0776f1SJuan Quintela bool migrate_background_snapshot(void) 331f0776f1SJuan Quintela { 341f0776f1SJuan Quintela MigrationState *s; 351f0776f1SJuan Quintela 361f0776f1SJuan Quintela s = migrate_get_current(); 371f0776f1SJuan Quintela 381f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT]; 391f0776f1SJuan Quintela } 401f0776f1SJuan Quintela 419d4b1e5fSJuan Quintela bool migrate_block(void) 429d4b1e5fSJuan Quintela { 439d4b1e5fSJuan Quintela MigrationState *s; 449d4b1e5fSJuan Quintela 459d4b1e5fSJuan Quintela s = migrate_get_current(); 469d4b1e5fSJuan Quintela 479d4b1e5fSJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_BLOCK]; 489d4b1e5fSJuan Quintela } 499d4b1e5fSJuan Quintela 505e804644SJuan Quintela bool migrate_colo(void) 515e804644SJuan Quintela { 525e804644SJuan Quintela MigrationState *s = migrate_get_current(); 535e804644SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_X_COLO]; 545e804644SJuan Quintela } 555e804644SJuan Quintela 56a7a94d14SJuan Quintela bool migrate_compress(void) 57a7a94d14SJuan Quintela { 58a7a94d14SJuan Quintela MigrationState *s; 59a7a94d14SJuan Quintela 60a7a94d14SJuan Quintela s = migrate_get_current(); 61a7a94d14SJuan Quintela 62a7a94d14SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_COMPRESS]; 63a7a94d14SJuan Quintela } 64a7a94d14SJuan Quintela 651f0776f1SJuan Quintela bool migrate_dirty_bitmaps(void) 661f0776f1SJuan Quintela { 671f0776f1SJuan Quintela MigrationState *s; 681f0776f1SJuan Quintela 691f0776f1SJuan Quintela s = migrate_get_current(); 701f0776f1SJuan Quintela 711f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_DIRTY_BITMAPS]; 721f0776f1SJuan Quintela } 731f0776f1SJuan Quintela 74b890902cSJuan Quintela bool migrate_events(void) 75b890902cSJuan Quintela { 76b890902cSJuan Quintela MigrationState *s; 77b890902cSJuan Quintela 78b890902cSJuan Quintela s = migrate_get_current(); 79b890902cSJuan Quintela 80b890902cSJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_EVENTS]; 81b890902cSJuan Quintela } 82b890902cSJuan Quintela 831f0776f1SJuan Quintela bool migrate_ignore_shared(void) 841f0776f1SJuan Quintela { 851f0776f1SJuan Quintela MigrationState *s; 861f0776f1SJuan Quintela 871f0776f1SJuan Quintela s = migrate_get_current(); 881f0776f1SJuan Quintela 891f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_X_IGNORE_SHARED]; 901f0776f1SJuan Quintela } 911f0776f1SJuan Quintela 921f0776f1SJuan Quintela bool migrate_late_block_activate(void) 931f0776f1SJuan Quintela { 941f0776f1SJuan Quintela MigrationState *s; 951f0776f1SJuan Quintela 961f0776f1SJuan Quintela s = migrate_get_current(); 971f0776f1SJuan Quintela 981f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE]; 991f0776f1SJuan Quintela } 1001f0776f1SJuan Quintela 10151b07548SJuan Quintela bool migrate_multifd(void) 10251b07548SJuan Quintela { 10351b07548SJuan Quintela MigrationState *s; 10451b07548SJuan Quintela 10551b07548SJuan Quintela s = migrate_get_current(); 10651b07548SJuan Quintela 10751b07548SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_MULTIFD]; 10851b07548SJuan Quintela } 10951b07548SJuan Quintela 1101f0776f1SJuan Quintela bool migrate_pause_before_switchover(void) 1111f0776f1SJuan Quintela { 1121f0776f1SJuan Quintela MigrationState *s; 1131f0776f1SJuan Quintela 1141f0776f1SJuan Quintela s = migrate_get_current(); 1151f0776f1SJuan Quintela 1161f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER]; 1171f0776f1SJuan Quintela } 1181f0776f1SJuan Quintela 1191f0776f1SJuan Quintela bool migrate_postcopy_blocktime(void) 1201f0776f1SJuan Quintela { 1211f0776f1SJuan Quintela MigrationState *s; 1221f0776f1SJuan Quintela 1231f0776f1SJuan Quintela s = migrate_get_current(); 1241f0776f1SJuan Quintela 1251f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME]; 1261f0776f1SJuan Quintela } 1271f0776f1SJuan Quintela 1281f0776f1SJuan Quintela bool migrate_postcopy_preempt(void) 1291f0776f1SJuan Quintela { 1301f0776f1SJuan Quintela MigrationState *s; 1311f0776f1SJuan Quintela 1321f0776f1SJuan Quintela s = migrate_get_current(); 1331f0776f1SJuan Quintela 1341f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT]; 1351f0776f1SJuan Quintela } 1361f0776f1SJuan Quintela 1371f0776f1SJuan Quintela bool migrate_postcopy_ram(void) 1381f0776f1SJuan Quintela { 1391f0776f1SJuan Quintela MigrationState *s; 1401f0776f1SJuan Quintela 1411f0776f1SJuan Quintela s = migrate_get_current(); 1421f0776f1SJuan Quintela 1431f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_RAM]; 1441f0776f1SJuan Quintela } 1451f0776f1SJuan Quintela 14617cba690SJuan Quintela bool migrate_rdma_pin_all(void) 14717cba690SJuan Quintela { 14817cba690SJuan Quintela MigrationState *s = migrate_get_current(); 14917cba690SJuan Quintela 15017cba690SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_RDMA_PIN_ALL]; 15117cba690SJuan Quintela } 15217cba690SJuan Quintela 1531f0776f1SJuan Quintela bool migrate_release_ram(void) 1541f0776f1SJuan Quintela { 1551f0776f1SJuan Quintela MigrationState *s; 1561f0776f1SJuan Quintela 1571f0776f1SJuan Quintela s = migrate_get_current(); 1581f0776f1SJuan Quintela 1591f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_RELEASE_RAM]; 1601f0776f1SJuan Quintela } 1611f0776f1SJuan Quintela 16238ad1110SJuan Quintela bool migrate_return_path(void) 16338ad1110SJuan Quintela { 16438ad1110SJuan Quintela MigrationState *s; 16538ad1110SJuan Quintela 16638ad1110SJuan Quintela s = migrate_get_current(); 16738ad1110SJuan Quintela 16838ad1110SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_RETURN_PATH]; 16938ad1110SJuan Quintela } 17038ad1110SJuan Quintela 1711f0776f1SJuan Quintela bool migrate_validate_uuid(void) 1721f0776f1SJuan Quintela { 1731f0776f1SJuan Quintela MigrationState *s; 1741f0776f1SJuan Quintela 1751f0776f1SJuan Quintela s = migrate_get_current(); 1761f0776f1SJuan Quintela 1771f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_VALIDATE_UUID]; 1781f0776f1SJuan Quintela } 1791f0776f1SJuan Quintela 18087dca0c9SJuan Quintela bool migrate_xbzrle(void) 18187dca0c9SJuan Quintela { 18287dca0c9SJuan Quintela MigrationState *s; 18387dca0c9SJuan Quintela 18487dca0c9SJuan Quintela s = migrate_get_current(); 18587dca0c9SJuan Quintela 18687dca0c9SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_XBZRLE]; 18787dca0c9SJuan Quintela } 18887dca0c9SJuan Quintela 1891f0776f1SJuan Quintela bool migrate_zero_blocks(void) 1901f0776f1SJuan Quintela { 1911f0776f1SJuan Quintela MigrationState *s; 1921f0776f1SJuan Quintela 1931f0776f1SJuan Quintela s = migrate_get_current(); 1941f0776f1SJuan Quintela 1951f0776f1SJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_ZERO_BLOCKS]; 1961f0776f1SJuan Quintela } 197b4bc342cSJuan Quintela 198b4bc342cSJuan Quintela bool migrate_zero_copy_send(void) 199b4bc342cSJuan Quintela { 200b4bc342cSJuan Quintela MigrationState *s; 201b4bc342cSJuan Quintela 202b4bc342cSJuan Quintela s = migrate_get_current(); 203b4bc342cSJuan Quintela 204b4bc342cSJuan Quintela return s->capabilities[MIGRATION_CAPABILITY_ZERO_COPY_SEND]; 205b4bc342cSJuan Quintela } 20677608706SJuan Quintela typedef enum WriteTrackingSupport { 20777608706SJuan Quintela WT_SUPPORT_UNKNOWN = 0, 20877608706SJuan Quintela WT_SUPPORT_ABSENT, 20977608706SJuan Quintela WT_SUPPORT_AVAILABLE, 21077608706SJuan Quintela WT_SUPPORT_COMPATIBLE 21177608706SJuan Quintela } WriteTrackingSupport; 21277608706SJuan Quintela 21377608706SJuan Quintela static 21477608706SJuan Quintela WriteTrackingSupport migrate_query_write_tracking(void) 21577608706SJuan Quintela { 21677608706SJuan Quintela /* Check if kernel supports required UFFD features */ 21777608706SJuan Quintela if (!ram_write_tracking_available()) { 21877608706SJuan Quintela return WT_SUPPORT_ABSENT; 21977608706SJuan Quintela } 22077608706SJuan Quintela /* 22177608706SJuan Quintela * Check if current memory configuration is 22277608706SJuan Quintela * compatible with required UFFD features. 22377608706SJuan Quintela */ 22477608706SJuan Quintela if (!ram_write_tracking_compatible()) { 22577608706SJuan Quintela return WT_SUPPORT_AVAILABLE; 22677608706SJuan Quintela } 22777608706SJuan Quintela 22877608706SJuan Quintela return WT_SUPPORT_COMPATIBLE; 22977608706SJuan Quintela } 23077608706SJuan Quintela 23177608706SJuan Quintela /* Migration capabilities set */ 23277608706SJuan Quintela struct MigrateCapsSet { 23377608706SJuan Quintela int size; /* Capability set size */ 23477608706SJuan Quintela MigrationCapability caps[]; /* Variadic array of capabilities */ 23577608706SJuan Quintela }; 23677608706SJuan Quintela typedef struct MigrateCapsSet MigrateCapsSet; 23777608706SJuan Quintela 23877608706SJuan Quintela /* Define and initialize MigrateCapsSet */ 23977608706SJuan Quintela #define INITIALIZE_MIGRATE_CAPS_SET(_name, ...) \ 24077608706SJuan Quintela MigrateCapsSet _name = { \ 24177608706SJuan Quintela .size = sizeof((int []) { __VA_ARGS__ }) / sizeof(int), \ 24277608706SJuan Quintela .caps = { __VA_ARGS__ } \ 24377608706SJuan Quintela } 24477608706SJuan Quintela 24577608706SJuan Quintela /* Background-snapshot compatibility check list */ 24677608706SJuan Quintela static const 24777608706SJuan Quintela INITIALIZE_MIGRATE_CAPS_SET(check_caps_background_snapshot, 24877608706SJuan Quintela MIGRATION_CAPABILITY_POSTCOPY_RAM, 24977608706SJuan Quintela MIGRATION_CAPABILITY_DIRTY_BITMAPS, 25077608706SJuan Quintela MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME, 25177608706SJuan Quintela MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE, 25277608706SJuan Quintela MIGRATION_CAPABILITY_RETURN_PATH, 25377608706SJuan Quintela MIGRATION_CAPABILITY_MULTIFD, 25477608706SJuan Quintela MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER, 25577608706SJuan Quintela MIGRATION_CAPABILITY_AUTO_CONVERGE, 25677608706SJuan Quintela MIGRATION_CAPABILITY_RELEASE_RAM, 25777608706SJuan Quintela MIGRATION_CAPABILITY_RDMA_PIN_ALL, 25877608706SJuan Quintela MIGRATION_CAPABILITY_COMPRESS, 25977608706SJuan Quintela MIGRATION_CAPABILITY_XBZRLE, 26077608706SJuan Quintela MIGRATION_CAPABILITY_X_COLO, 26177608706SJuan Quintela MIGRATION_CAPABILITY_VALIDATE_UUID, 26277608706SJuan Quintela MIGRATION_CAPABILITY_ZERO_COPY_SEND); 26377608706SJuan Quintela 26477608706SJuan Quintela /** 26577608706SJuan Quintela * @migration_caps_check - check capability compatibility 26677608706SJuan Quintela * 26777608706SJuan Quintela * @old_caps: old capability list 26877608706SJuan Quintela * @new_caps: new capability list 26977608706SJuan Quintela * @errp: set *errp if the check failed, with reason 27077608706SJuan Quintela * 27177608706SJuan Quintela * Returns true if check passed, otherwise false. 27277608706SJuan Quintela */ 27377608706SJuan Quintela bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp) 27477608706SJuan Quintela { 27577608706SJuan Quintela MigrationIncomingState *mis = migration_incoming_get_current(); 27677608706SJuan Quintela 27777608706SJuan Quintela #ifndef CONFIG_LIVE_BLOCK_MIGRATION 27877608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_BLOCK]) { 27977608706SJuan Quintela error_setg(errp, "QEMU compiled without old-style (blk/-b, inc/-i) " 28077608706SJuan Quintela "block migration"); 28177608706SJuan Quintela error_append_hint(errp, "Use drive_mirror+NBD instead.\n"); 28277608706SJuan Quintela return false; 28377608706SJuan Quintela } 28477608706SJuan Quintela #endif 28577608706SJuan Quintela 28677608706SJuan Quintela #ifndef CONFIG_REPLICATION 28777608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_X_COLO]) { 28877608706SJuan Quintela error_setg(errp, "QEMU compiled without replication module" 28977608706SJuan Quintela " can't enable COLO"); 29077608706SJuan Quintela error_append_hint(errp, "Please enable replication before COLO.\n"); 29177608706SJuan Quintela return false; 29277608706SJuan Quintela } 29377608706SJuan Quintela #endif 29477608706SJuan Quintela 29577608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) { 29677608706SJuan Quintela /* This check is reasonably expensive, so only when it's being 29777608706SJuan Quintela * set the first time, also it's only the destination that needs 29877608706SJuan Quintela * special support. 29977608706SJuan Quintela */ 30077608706SJuan Quintela if (!old_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM] && 30177608706SJuan Quintela runstate_check(RUN_STATE_INMIGRATE) && 30277608706SJuan Quintela !postcopy_ram_supported_by_host(mis)) { 30377608706SJuan Quintela /* postcopy_ram_supported_by_host will have emitted a more 30477608706SJuan Quintela * detailed message 30577608706SJuan Quintela */ 30677608706SJuan Quintela error_setg(errp, "Postcopy is not supported"); 30777608706SJuan Quintela return false; 30877608706SJuan Quintela } 30977608706SJuan Quintela 31077608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_X_IGNORE_SHARED]) { 31177608706SJuan Quintela error_setg(errp, "Postcopy is not compatible with ignore-shared"); 31277608706SJuan Quintela return false; 31377608706SJuan Quintela } 31477608706SJuan Quintela } 31577608706SJuan Quintela 31677608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT]) { 31777608706SJuan Quintela WriteTrackingSupport wt_support; 31877608706SJuan Quintela int idx; 31977608706SJuan Quintela /* 32077608706SJuan Quintela * Check if 'background-snapshot' capability is supported by 32177608706SJuan Quintela * host kernel and compatible with guest memory configuration. 32277608706SJuan Quintela */ 32377608706SJuan Quintela wt_support = migrate_query_write_tracking(); 32477608706SJuan Quintela if (wt_support < WT_SUPPORT_AVAILABLE) { 32577608706SJuan Quintela error_setg(errp, "Background-snapshot is not supported by host kernel"); 32677608706SJuan Quintela return false; 32777608706SJuan Quintela } 32877608706SJuan Quintela if (wt_support < WT_SUPPORT_COMPATIBLE) { 32977608706SJuan Quintela error_setg(errp, "Background-snapshot is not compatible " 33077608706SJuan Quintela "with guest memory configuration"); 33177608706SJuan Quintela return false; 33277608706SJuan Quintela } 33377608706SJuan Quintela 33477608706SJuan Quintela /* 33577608706SJuan Quintela * Check if there are any migration capabilities 33677608706SJuan Quintela * incompatible with 'background-snapshot'. 33777608706SJuan Quintela */ 33877608706SJuan Quintela for (idx = 0; idx < check_caps_background_snapshot.size; idx++) { 33977608706SJuan Quintela int incomp_cap = check_caps_background_snapshot.caps[idx]; 34077608706SJuan Quintela if (new_caps[incomp_cap]) { 34177608706SJuan Quintela error_setg(errp, 34277608706SJuan Quintela "Background-snapshot is not compatible with %s", 34377608706SJuan Quintela MigrationCapability_str(incomp_cap)); 34477608706SJuan Quintela return false; 34577608706SJuan Quintela } 34677608706SJuan Quintela } 34777608706SJuan Quintela } 34877608706SJuan Quintela 34977608706SJuan Quintela #ifdef CONFIG_LINUX 35077608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND] && 35177608706SJuan Quintela (!new_caps[MIGRATION_CAPABILITY_MULTIFD] || 35277608706SJuan Quintela new_caps[MIGRATION_CAPABILITY_COMPRESS] || 35377608706SJuan Quintela new_caps[MIGRATION_CAPABILITY_XBZRLE] || 35477608706SJuan Quintela migrate_multifd_compression() || 35577608706SJuan Quintela migrate_use_tls())) { 35677608706SJuan Quintela error_setg(errp, 35777608706SJuan Quintela "Zero copy only available for non-compressed non-TLS multifd migration"); 35877608706SJuan Quintela return false; 35977608706SJuan Quintela } 36077608706SJuan Quintela #else 36177608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND]) { 36277608706SJuan Quintela error_setg(errp, 36377608706SJuan Quintela "Zero copy currently only available on Linux"); 36477608706SJuan Quintela return false; 36577608706SJuan Quintela } 36677608706SJuan Quintela #endif 36777608706SJuan Quintela 36877608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT]) { 36977608706SJuan Quintela if (!new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) { 37077608706SJuan Quintela error_setg(errp, "Postcopy preempt requires postcopy-ram"); 37177608706SJuan Quintela return false; 37277608706SJuan Quintela } 37377608706SJuan Quintela 37477608706SJuan Quintela /* 37577608706SJuan Quintela * Preempt mode requires urgent pages to be sent in separate 37677608706SJuan Quintela * channel, OTOH compression logic will disorder all pages into 37777608706SJuan Quintela * different compression channels, which is not compatible with the 37877608706SJuan Quintela * preempt assumptions on channel assignments. 37977608706SJuan Quintela */ 38077608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) { 38177608706SJuan Quintela error_setg(errp, "Postcopy preempt not compatible with compress"); 38277608706SJuan Quintela return false; 38377608706SJuan Quintela } 38477608706SJuan Quintela } 38577608706SJuan Quintela 38677608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) { 38777608706SJuan Quintela if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) { 38877608706SJuan Quintela error_setg(errp, "Multifd is not compatible with compress"); 38977608706SJuan Quintela return false; 39077608706SJuan Quintela } 39177608706SJuan Quintela } 39277608706SJuan Quintela 39377608706SJuan Quintela return true; 39477608706SJuan Quintela } 3954d0c6b69SJuan Quintela 396*f80196b7SJuan Quintela bool migrate_cap_set(int cap, bool value, Error **errp) 397*f80196b7SJuan Quintela { 398*f80196b7SJuan Quintela MigrationState *s = migrate_get_current(); 399*f80196b7SJuan Quintela bool new_caps[MIGRATION_CAPABILITY__MAX]; 400*f80196b7SJuan Quintela 401*f80196b7SJuan Quintela if (migration_is_running(s->state)) { 402*f80196b7SJuan Quintela error_setg(errp, QERR_MIGRATION_ACTIVE); 403*f80196b7SJuan Quintela return false; 404*f80196b7SJuan Quintela } 405*f80196b7SJuan Quintela 406*f80196b7SJuan Quintela memcpy(new_caps, s->capabilities, sizeof(new_caps)); 407*f80196b7SJuan Quintela new_caps[cap] = value; 408*f80196b7SJuan Quintela 409*f80196b7SJuan Quintela if (!migrate_caps_check(s->capabilities, new_caps, errp)) { 410*f80196b7SJuan Quintela return false; 411*f80196b7SJuan Quintela } 412*f80196b7SJuan Quintela s->capabilities[cap] = value; 413*f80196b7SJuan Quintela return true; 414*f80196b7SJuan Quintela } 415*f80196b7SJuan Quintela 4164d0c6b69SJuan Quintela MigrationCapabilityStatusList *qmp_query_migrate_capabilities(Error **errp) 4174d0c6b69SJuan Quintela { 4184d0c6b69SJuan Quintela MigrationCapabilityStatusList *head = NULL, **tail = &head; 4194d0c6b69SJuan Quintela MigrationCapabilityStatus *caps; 4204d0c6b69SJuan Quintela MigrationState *s = migrate_get_current(); 4214d0c6b69SJuan Quintela int i; 4224d0c6b69SJuan Quintela 4234d0c6b69SJuan Quintela for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) { 4244d0c6b69SJuan Quintela #ifndef CONFIG_LIVE_BLOCK_MIGRATION 4254d0c6b69SJuan Quintela if (i == MIGRATION_CAPABILITY_BLOCK) { 4264d0c6b69SJuan Quintela continue; 4274d0c6b69SJuan Quintela } 4284d0c6b69SJuan Quintela #endif 4294d0c6b69SJuan Quintela caps = g_malloc0(sizeof(*caps)); 4304d0c6b69SJuan Quintela caps->capability = i; 4314d0c6b69SJuan Quintela caps->state = s->capabilities[i]; 4324d0c6b69SJuan Quintela QAPI_LIST_APPEND(tail, caps); 4334d0c6b69SJuan Quintela } 4344d0c6b69SJuan Quintela 4354d0c6b69SJuan Quintela return head; 4364d0c6b69SJuan Quintela } 43745c1de13SJuan Quintela 43845c1de13SJuan Quintela void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params, 43945c1de13SJuan Quintela Error **errp) 44045c1de13SJuan Quintela { 44145c1de13SJuan Quintela MigrationState *s = migrate_get_current(); 44245c1de13SJuan Quintela MigrationCapabilityStatusList *cap; 44345c1de13SJuan Quintela bool new_caps[MIGRATION_CAPABILITY__MAX]; 44445c1de13SJuan Quintela 44545c1de13SJuan Quintela if (migration_is_running(s->state)) { 44645c1de13SJuan Quintela error_setg(errp, QERR_MIGRATION_ACTIVE); 44745c1de13SJuan Quintela return; 44845c1de13SJuan Quintela } 44945c1de13SJuan Quintela 45045c1de13SJuan Quintela memcpy(new_caps, s->capabilities, sizeof(new_caps)); 45145c1de13SJuan Quintela for (cap = params; cap; cap = cap->next) { 45245c1de13SJuan Quintela new_caps[cap->value->capability] = cap->value->state; 45345c1de13SJuan Quintela } 45445c1de13SJuan Quintela 45545c1de13SJuan Quintela if (!migrate_caps_check(s->capabilities, new_caps, errp)) { 45645c1de13SJuan Quintela return; 45745c1de13SJuan Quintela } 45845c1de13SJuan Quintela 45945c1de13SJuan Quintela for (cap = params; cap; cap = cap->next) { 46045c1de13SJuan Quintela s->capabilities[cap->value->capability] = cap->value->state; 46145c1de13SJuan Quintela } 46245c1de13SJuan Quintela } 463