1 /* 2 * QEMU migration capabilities 3 * 4 * Copyright (c) 2012-2023 Red Hat Inc 5 * 6 * Authors: 7 * Orit Wasserman <owasserm@redhat.com> 8 * Juan Quintela <quintela@redhat.com> 9 * 10 * This work is licensed under the terms of the GNU GPL, version 2 or later. 11 * See the COPYING file in the top-level directory. 12 */ 13 14 #include "qemu/osdep.h" 15 #include "exec/target_page.h" 16 #include "qapi/clone-visitor.h" 17 #include "qapi/error.h" 18 #include "qapi/qapi-commands-migration.h" 19 #include "qapi/qapi-visit-migration.h" 20 #include "qapi/qmp/qerror.h" 21 #include "qapi/qmp/qnull.h" 22 #include "sysemu/runstate.h" 23 #include "migration/colo.h" 24 #include "migration/misc.h" 25 #include "migration.h" 26 #include "qemu-file.h" 27 #include "ram.h" 28 #include "options.h" 29 30 /* Maximum migrate downtime set to 2000 seconds */ 31 #define MAX_MIGRATE_DOWNTIME_SECONDS 2000 32 #define MAX_MIGRATE_DOWNTIME (MAX_MIGRATE_DOWNTIME_SECONDS * 1000) 33 34 bool migrate_auto_converge(void) 35 { 36 MigrationState *s = migrate_get_current(); 37 38 return s->capabilities[MIGRATION_CAPABILITY_AUTO_CONVERGE]; 39 } 40 41 bool migrate_background_snapshot(void) 42 { 43 MigrationState *s = migrate_get_current(); 44 45 return s->capabilities[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT]; 46 } 47 48 bool migrate_block(void) 49 { 50 MigrationState *s = migrate_get_current(); 51 52 return s->capabilities[MIGRATION_CAPABILITY_BLOCK]; 53 } 54 55 bool migrate_colo(void) 56 { 57 MigrationState *s = migrate_get_current(); 58 59 return s->capabilities[MIGRATION_CAPABILITY_X_COLO]; 60 } 61 62 bool migrate_compress(void) 63 { 64 MigrationState *s = migrate_get_current(); 65 66 return s->capabilities[MIGRATION_CAPABILITY_COMPRESS]; 67 } 68 69 bool migrate_dirty_bitmaps(void) 70 { 71 MigrationState *s = migrate_get_current(); 72 73 return s->capabilities[MIGRATION_CAPABILITY_DIRTY_BITMAPS]; 74 } 75 76 bool migrate_events(void) 77 { 78 MigrationState *s = migrate_get_current(); 79 80 return s->capabilities[MIGRATION_CAPABILITY_EVENTS]; 81 } 82 83 bool migrate_ignore_shared(void) 84 { 85 MigrationState *s = migrate_get_current(); 86 87 return s->capabilities[MIGRATION_CAPABILITY_X_IGNORE_SHARED]; 88 } 89 90 bool migrate_late_block_activate(void) 91 { 92 MigrationState *s = migrate_get_current(); 93 94 return s->capabilities[MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE]; 95 } 96 97 bool migrate_multifd(void) 98 { 99 MigrationState *s = migrate_get_current(); 100 101 return s->capabilities[MIGRATION_CAPABILITY_MULTIFD]; 102 } 103 104 bool migrate_pause_before_switchover(void) 105 { 106 MigrationState *s = migrate_get_current(); 107 108 return s->capabilities[MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER]; 109 } 110 111 bool migrate_postcopy_blocktime(void) 112 { 113 MigrationState *s = migrate_get_current(); 114 115 return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME]; 116 } 117 118 bool migrate_postcopy_preempt(void) 119 { 120 MigrationState *s = migrate_get_current(); 121 122 return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT]; 123 } 124 125 bool migrate_postcopy_ram(void) 126 { 127 MigrationState *s = migrate_get_current(); 128 129 return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_RAM]; 130 } 131 132 bool migrate_rdma_pin_all(void) 133 { 134 MigrationState *s = migrate_get_current(); 135 136 return s->capabilities[MIGRATION_CAPABILITY_RDMA_PIN_ALL]; 137 } 138 139 bool migrate_release_ram(void) 140 { 141 MigrationState *s = migrate_get_current(); 142 143 return s->capabilities[MIGRATION_CAPABILITY_RELEASE_RAM]; 144 } 145 146 bool migrate_return_path(void) 147 { 148 MigrationState *s = migrate_get_current(); 149 150 return s->capabilities[MIGRATION_CAPABILITY_RETURN_PATH]; 151 } 152 153 bool migrate_validate_uuid(void) 154 { 155 MigrationState *s = migrate_get_current(); 156 157 return s->capabilities[MIGRATION_CAPABILITY_VALIDATE_UUID]; 158 } 159 160 bool migrate_xbzrle(void) 161 { 162 MigrationState *s = migrate_get_current(); 163 164 return s->capabilities[MIGRATION_CAPABILITY_XBZRLE]; 165 } 166 167 bool migrate_zero_blocks(void) 168 { 169 MigrationState *s = migrate_get_current(); 170 171 return s->capabilities[MIGRATION_CAPABILITY_ZERO_BLOCKS]; 172 } 173 174 bool migrate_zero_copy_send(void) 175 { 176 MigrationState *s = migrate_get_current(); 177 178 return s->capabilities[MIGRATION_CAPABILITY_ZERO_COPY_SEND]; 179 } 180 181 /* pseudo capabilities */ 182 183 bool migrate_postcopy(void) 184 { 185 return migrate_postcopy_ram() || migrate_dirty_bitmaps(); 186 } 187 188 bool migrate_tls(void) 189 { 190 MigrationState *s = migrate_get_current(); 191 192 return s->parameters.tls_creds && *s->parameters.tls_creds; 193 } 194 195 typedef enum WriteTrackingSupport { 196 WT_SUPPORT_UNKNOWN = 0, 197 WT_SUPPORT_ABSENT, 198 WT_SUPPORT_AVAILABLE, 199 WT_SUPPORT_COMPATIBLE 200 } WriteTrackingSupport; 201 202 static 203 WriteTrackingSupport migrate_query_write_tracking(void) 204 { 205 /* Check if kernel supports required UFFD features */ 206 if (!ram_write_tracking_available()) { 207 return WT_SUPPORT_ABSENT; 208 } 209 /* 210 * Check if current memory configuration is 211 * compatible with required UFFD features. 212 */ 213 if (!ram_write_tracking_compatible()) { 214 return WT_SUPPORT_AVAILABLE; 215 } 216 217 return WT_SUPPORT_COMPATIBLE; 218 } 219 220 /* Migration capabilities set */ 221 struct MigrateCapsSet { 222 int size; /* Capability set size */ 223 MigrationCapability caps[]; /* Variadic array of capabilities */ 224 }; 225 typedef struct MigrateCapsSet MigrateCapsSet; 226 227 /* Define and initialize MigrateCapsSet */ 228 #define INITIALIZE_MIGRATE_CAPS_SET(_name, ...) \ 229 MigrateCapsSet _name = { \ 230 .size = sizeof((int []) { __VA_ARGS__ }) / sizeof(int), \ 231 .caps = { __VA_ARGS__ } \ 232 } 233 234 /* Background-snapshot compatibility check list */ 235 static const 236 INITIALIZE_MIGRATE_CAPS_SET(check_caps_background_snapshot, 237 MIGRATION_CAPABILITY_POSTCOPY_RAM, 238 MIGRATION_CAPABILITY_DIRTY_BITMAPS, 239 MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME, 240 MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE, 241 MIGRATION_CAPABILITY_RETURN_PATH, 242 MIGRATION_CAPABILITY_MULTIFD, 243 MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER, 244 MIGRATION_CAPABILITY_AUTO_CONVERGE, 245 MIGRATION_CAPABILITY_RELEASE_RAM, 246 MIGRATION_CAPABILITY_RDMA_PIN_ALL, 247 MIGRATION_CAPABILITY_COMPRESS, 248 MIGRATION_CAPABILITY_XBZRLE, 249 MIGRATION_CAPABILITY_X_COLO, 250 MIGRATION_CAPABILITY_VALIDATE_UUID, 251 MIGRATION_CAPABILITY_ZERO_COPY_SEND); 252 253 /** 254 * @migration_caps_check - check capability compatibility 255 * 256 * @old_caps: old capability list 257 * @new_caps: new capability list 258 * @errp: set *errp if the check failed, with reason 259 * 260 * Returns true if check passed, otherwise false. 261 */ 262 bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp) 263 { 264 MigrationIncomingState *mis = migration_incoming_get_current(); 265 266 ERRP_GUARD(); 267 #ifndef CONFIG_LIVE_BLOCK_MIGRATION 268 if (new_caps[MIGRATION_CAPABILITY_BLOCK]) { 269 error_setg(errp, "QEMU compiled without old-style (blk/-b, inc/-i) " 270 "block migration"); 271 error_append_hint(errp, "Use drive_mirror+NBD instead.\n"); 272 return false; 273 } 274 #endif 275 276 #ifndef CONFIG_REPLICATION 277 if (new_caps[MIGRATION_CAPABILITY_X_COLO]) { 278 error_setg(errp, "QEMU compiled without replication module" 279 " can't enable COLO"); 280 error_append_hint(errp, "Please enable replication before COLO.\n"); 281 return false; 282 } 283 #endif 284 285 if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) { 286 /* This check is reasonably expensive, so only when it's being 287 * set the first time, also it's only the destination that needs 288 * special support. 289 */ 290 if (!old_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM] && 291 runstate_check(RUN_STATE_INMIGRATE) && 292 !postcopy_ram_supported_by_host(mis, errp)) { 293 error_prepend(errp, "Postcopy is not supported: "); 294 return false; 295 } 296 297 if (new_caps[MIGRATION_CAPABILITY_X_IGNORE_SHARED]) { 298 error_setg(errp, "Postcopy is not compatible with ignore-shared"); 299 return false; 300 } 301 302 if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) { 303 error_setg(errp, "Postcopy is not yet compatible with multifd"); 304 return false; 305 } 306 } 307 308 if (new_caps[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT]) { 309 WriteTrackingSupport wt_support; 310 int idx; 311 /* 312 * Check if 'background-snapshot' capability is supported by 313 * host kernel and compatible with guest memory configuration. 314 */ 315 wt_support = migrate_query_write_tracking(); 316 if (wt_support < WT_SUPPORT_AVAILABLE) { 317 error_setg(errp, "Background-snapshot is not supported by host kernel"); 318 return false; 319 } 320 if (wt_support < WT_SUPPORT_COMPATIBLE) { 321 error_setg(errp, "Background-snapshot is not compatible " 322 "with guest memory configuration"); 323 return false; 324 } 325 326 /* 327 * Check if there are any migration capabilities 328 * incompatible with 'background-snapshot'. 329 */ 330 for (idx = 0; idx < check_caps_background_snapshot.size; idx++) { 331 int incomp_cap = check_caps_background_snapshot.caps[idx]; 332 if (new_caps[incomp_cap]) { 333 error_setg(errp, 334 "Background-snapshot is not compatible with %s", 335 MigrationCapability_str(incomp_cap)); 336 return false; 337 } 338 } 339 } 340 341 #ifdef CONFIG_LINUX 342 if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND] && 343 (!new_caps[MIGRATION_CAPABILITY_MULTIFD] || 344 new_caps[MIGRATION_CAPABILITY_COMPRESS] || 345 new_caps[MIGRATION_CAPABILITY_XBZRLE] || 346 migrate_multifd_compression() || 347 migrate_tls())) { 348 error_setg(errp, 349 "Zero copy only available for non-compressed non-TLS multifd migration"); 350 return false; 351 } 352 #else 353 if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND]) { 354 error_setg(errp, 355 "Zero copy currently only available on Linux"); 356 return false; 357 } 358 #endif 359 360 if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT]) { 361 if (!new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) { 362 error_setg(errp, "Postcopy preempt requires postcopy-ram"); 363 return false; 364 } 365 366 /* 367 * Preempt mode requires urgent pages to be sent in separate 368 * channel, OTOH compression logic will disorder all pages into 369 * different compression channels, which is not compatible with the 370 * preempt assumptions on channel assignments. 371 */ 372 if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) { 373 error_setg(errp, "Postcopy preempt not compatible with compress"); 374 return false; 375 } 376 } 377 378 if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) { 379 if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) { 380 error_setg(errp, "Multifd is not compatible with compress"); 381 return false; 382 } 383 } 384 385 return true; 386 } 387 388 bool migrate_cap_set(int cap, bool value, Error **errp) 389 { 390 MigrationState *s = migrate_get_current(); 391 bool new_caps[MIGRATION_CAPABILITY__MAX]; 392 393 if (migration_is_running(s->state)) { 394 error_setg(errp, QERR_MIGRATION_ACTIVE); 395 return false; 396 } 397 398 memcpy(new_caps, s->capabilities, sizeof(new_caps)); 399 new_caps[cap] = value; 400 401 if (!migrate_caps_check(s->capabilities, new_caps, errp)) { 402 return false; 403 } 404 s->capabilities[cap] = value; 405 return true; 406 } 407 408 MigrationCapabilityStatusList *qmp_query_migrate_capabilities(Error **errp) 409 { 410 MigrationCapabilityStatusList *head = NULL, **tail = &head; 411 MigrationCapabilityStatus *caps; 412 MigrationState *s = migrate_get_current(); 413 int i; 414 415 for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) { 416 #ifndef CONFIG_LIVE_BLOCK_MIGRATION 417 if (i == MIGRATION_CAPABILITY_BLOCK) { 418 continue; 419 } 420 #endif 421 caps = g_malloc0(sizeof(*caps)); 422 caps->capability = i; 423 caps->state = s->capabilities[i]; 424 QAPI_LIST_APPEND(tail, caps); 425 } 426 427 return head; 428 } 429 430 void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params, 431 Error **errp) 432 { 433 MigrationState *s = migrate_get_current(); 434 MigrationCapabilityStatusList *cap; 435 bool new_caps[MIGRATION_CAPABILITY__MAX]; 436 437 if (migration_is_running(s->state)) { 438 error_setg(errp, QERR_MIGRATION_ACTIVE); 439 return; 440 } 441 442 memcpy(new_caps, s->capabilities, sizeof(new_caps)); 443 for (cap = params; cap; cap = cap->next) { 444 new_caps[cap->value->capability] = cap->value->state; 445 } 446 447 if (!migrate_caps_check(s->capabilities, new_caps, errp)) { 448 return; 449 } 450 451 for (cap = params; cap; cap = cap->next) { 452 s->capabilities[cap->value->capability] = cap->value->state; 453 } 454 } 455 456 /* parameters */ 457 458 const BitmapMigrationNodeAliasList *migrate_block_bitmap_mapping(void) 459 { 460 MigrationState *s = migrate_get_current(); 461 462 return s->parameters.block_bitmap_mapping; 463 } 464 465 bool migrate_block_incremental(void) 466 { 467 MigrationState *s = migrate_get_current(); 468 469 return s->parameters.block_incremental; 470 } 471 472 uint32_t migrate_checkpoint_delay(void) 473 { 474 MigrationState *s = migrate_get_current(); 475 476 return s->parameters.x_checkpoint_delay; 477 } 478 479 int migrate_compress_level(void) 480 { 481 MigrationState *s = migrate_get_current(); 482 483 return s->parameters.compress_level; 484 } 485 486 int migrate_compress_threads(void) 487 { 488 MigrationState *s = migrate_get_current(); 489 490 return s->parameters.compress_threads; 491 } 492 493 int migrate_compress_wait_thread(void) 494 { 495 MigrationState *s = migrate_get_current(); 496 497 return s->parameters.compress_wait_thread; 498 } 499 500 uint8_t migrate_cpu_throttle_increment(void) 501 { 502 MigrationState *s = migrate_get_current(); 503 504 return s->parameters.cpu_throttle_increment; 505 } 506 507 uint8_t migrate_cpu_throttle_initial(void) 508 { 509 MigrationState *s = migrate_get_current(); 510 511 return s->parameters.cpu_throttle_initial; 512 } 513 514 bool migrate_cpu_throttle_tailslow(void) 515 { 516 MigrationState *s = migrate_get_current(); 517 518 return s->parameters.cpu_throttle_tailslow; 519 } 520 521 int migrate_decompress_threads(void) 522 { 523 MigrationState *s = migrate_get_current(); 524 525 return s->parameters.decompress_threads; 526 } 527 528 uint64_t migrate_downtime_limit(void) 529 { 530 MigrationState *s = migrate_get_current(); 531 532 return s->parameters.downtime_limit; 533 } 534 535 uint8_t migrate_max_cpu_throttle(void) 536 { 537 MigrationState *s = migrate_get_current(); 538 539 return s->parameters.max_cpu_throttle; 540 } 541 542 uint64_t migrate_max_bandwidth(void) 543 { 544 MigrationState *s = migrate_get_current(); 545 546 return s->parameters.max_bandwidth; 547 } 548 549 int64_t migrate_max_postcopy_bandwidth(void) 550 { 551 MigrationState *s = migrate_get_current(); 552 553 return s->parameters.max_postcopy_bandwidth; 554 } 555 556 int migrate_multifd_channels(void) 557 { 558 MigrationState *s = migrate_get_current(); 559 560 return s->parameters.multifd_channels; 561 } 562 563 MultiFDCompression migrate_multifd_compression(void) 564 { 565 MigrationState *s = migrate_get_current(); 566 567 assert(s->parameters.multifd_compression < MULTIFD_COMPRESSION__MAX); 568 return s->parameters.multifd_compression; 569 } 570 571 int migrate_multifd_zlib_level(void) 572 { 573 MigrationState *s = migrate_get_current(); 574 575 return s->parameters.multifd_zlib_level; 576 } 577 578 int migrate_multifd_zstd_level(void) 579 { 580 MigrationState *s = migrate_get_current(); 581 582 return s->parameters.multifd_zstd_level; 583 } 584 585 uint8_t migrate_throttle_trigger_threshold(void) 586 { 587 MigrationState *s = migrate_get_current(); 588 589 return s->parameters.throttle_trigger_threshold; 590 } 591 592 const char *migrate_tls_authz(void) 593 { 594 MigrationState *s = migrate_get_current(); 595 596 return s->parameters.tls_authz; 597 } 598 599 const char *migrate_tls_creds(void) 600 { 601 MigrationState *s = migrate_get_current(); 602 603 return s->parameters.tls_creds; 604 } 605 606 const char *migrate_tls_hostname(void) 607 { 608 MigrationState *s = migrate_get_current(); 609 610 return s->parameters.tls_hostname; 611 } 612 613 uint64_t migrate_xbzrle_cache_size(void) 614 { 615 MigrationState *s = migrate_get_current(); 616 617 return s->parameters.xbzrle_cache_size; 618 } 619 620 /* parameter setters */ 621 622 void migrate_set_block_incremental(bool value) 623 { 624 MigrationState *s = migrate_get_current(); 625 626 s->parameters.block_incremental = value; 627 } 628 629 /* parameters helpers */ 630 631 void block_cleanup_parameters(void) 632 { 633 MigrationState *s = migrate_get_current(); 634 635 if (s->must_remove_block_options) { 636 /* setting to false can never fail */ 637 migrate_cap_set(MIGRATION_CAPABILITY_BLOCK, false, &error_abort); 638 migrate_set_block_incremental(false); 639 s->must_remove_block_options = false; 640 } 641 } 642 643 AnnounceParameters *migrate_announce_params(void) 644 { 645 static AnnounceParameters ap; 646 647 MigrationState *s = migrate_get_current(); 648 649 ap.initial = s->parameters.announce_initial; 650 ap.max = s->parameters.announce_max; 651 ap.rounds = s->parameters.announce_rounds; 652 ap.step = s->parameters.announce_step; 653 654 return ≈ 655 } 656 657 MigrationParameters *qmp_query_migrate_parameters(Error **errp) 658 { 659 MigrationParameters *params; 660 MigrationState *s = migrate_get_current(); 661 662 /* TODO use QAPI_CLONE() instead of duplicating it inline */ 663 params = g_malloc0(sizeof(*params)); 664 params->has_compress_level = true; 665 params->compress_level = s->parameters.compress_level; 666 params->has_compress_threads = true; 667 params->compress_threads = s->parameters.compress_threads; 668 params->has_compress_wait_thread = true; 669 params->compress_wait_thread = s->parameters.compress_wait_thread; 670 params->has_decompress_threads = true; 671 params->decompress_threads = s->parameters.decompress_threads; 672 params->has_throttle_trigger_threshold = true; 673 params->throttle_trigger_threshold = s->parameters.throttle_trigger_threshold; 674 params->has_cpu_throttle_initial = true; 675 params->cpu_throttle_initial = s->parameters.cpu_throttle_initial; 676 params->has_cpu_throttle_increment = true; 677 params->cpu_throttle_increment = s->parameters.cpu_throttle_increment; 678 params->has_cpu_throttle_tailslow = true; 679 params->cpu_throttle_tailslow = s->parameters.cpu_throttle_tailslow; 680 params->tls_creds = g_strdup(s->parameters.tls_creds); 681 params->tls_hostname = g_strdup(s->parameters.tls_hostname); 682 params->tls_authz = g_strdup(s->parameters.tls_authz ? 683 s->parameters.tls_authz : ""); 684 params->has_max_bandwidth = true; 685 params->max_bandwidth = s->parameters.max_bandwidth; 686 params->has_downtime_limit = true; 687 params->downtime_limit = s->parameters.downtime_limit; 688 params->has_x_checkpoint_delay = true; 689 params->x_checkpoint_delay = s->parameters.x_checkpoint_delay; 690 params->has_block_incremental = true; 691 params->block_incremental = s->parameters.block_incremental; 692 params->has_multifd_channels = true; 693 params->multifd_channels = s->parameters.multifd_channels; 694 params->has_multifd_compression = true; 695 params->multifd_compression = s->parameters.multifd_compression; 696 params->has_multifd_zlib_level = true; 697 params->multifd_zlib_level = s->parameters.multifd_zlib_level; 698 params->has_multifd_zstd_level = true; 699 params->multifd_zstd_level = s->parameters.multifd_zstd_level; 700 params->has_xbzrle_cache_size = true; 701 params->xbzrle_cache_size = s->parameters.xbzrle_cache_size; 702 params->has_max_postcopy_bandwidth = true; 703 params->max_postcopy_bandwidth = s->parameters.max_postcopy_bandwidth; 704 params->has_max_cpu_throttle = true; 705 params->max_cpu_throttle = s->parameters.max_cpu_throttle; 706 params->has_announce_initial = true; 707 params->announce_initial = s->parameters.announce_initial; 708 params->has_announce_max = true; 709 params->announce_max = s->parameters.announce_max; 710 params->has_announce_rounds = true; 711 params->announce_rounds = s->parameters.announce_rounds; 712 params->has_announce_step = true; 713 params->announce_step = s->parameters.announce_step; 714 715 if (s->parameters.has_block_bitmap_mapping) { 716 params->has_block_bitmap_mapping = true; 717 params->block_bitmap_mapping = 718 QAPI_CLONE(BitmapMigrationNodeAliasList, 719 s->parameters.block_bitmap_mapping); 720 } 721 722 return params; 723 } 724 725 void migrate_params_init(MigrationParameters *params) 726 { 727 params->tls_hostname = g_strdup(""); 728 params->tls_creds = g_strdup(""); 729 730 /* Set has_* up only for parameter checks */ 731 params->has_compress_level = true; 732 params->has_compress_threads = true; 733 params->has_compress_wait_thread = true; 734 params->has_decompress_threads = true; 735 params->has_throttle_trigger_threshold = true; 736 params->has_cpu_throttle_initial = true; 737 params->has_cpu_throttle_increment = true; 738 params->has_cpu_throttle_tailslow = true; 739 params->has_max_bandwidth = true; 740 params->has_downtime_limit = true; 741 params->has_x_checkpoint_delay = true; 742 params->has_block_incremental = true; 743 params->has_multifd_channels = true; 744 params->has_multifd_compression = true; 745 params->has_multifd_zlib_level = true; 746 params->has_multifd_zstd_level = true; 747 params->has_xbzrle_cache_size = true; 748 params->has_max_postcopy_bandwidth = true; 749 params->has_max_cpu_throttle = true; 750 params->has_announce_initial = true; 751 params->has_announce_max = true; 752 params->has_announce_rounds = true; 753 params->has_announce_step = true; 754 } 755 756 /* 757 * Check whether the parameters are valid. Error will be put into errp 758 * (if provided). Return true if valid, otherwise false. 759 */ 760 bool migrate_params_check(MigrationParameters *params, Error **errp) 761 { 762 if (params->has_compress_level && 763 (params->compress_level > 9)) { 764 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "compress_level", 765 "a value between 0 and 9"); 766 return false; 767 } 768 769 if (params->has_compress_threads && (params->compress_threads < 1)) { 770 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 771 "compress_threads", 772 "a value between 1 and 255"); 773 return false; 774 } 775 776 if (params->has_decompress_threads && (params->decompress_threads < 1)) { 777 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 778 "decompress_threads", 779 "a value between 1 and 255"); 780 return false; 781 } 782 783 if (params->has_throttle_trigger_threshold && 784 (params->throttle_trigger_threshold < 1 || 785 params->throttle_trigger_threshold > 100)) { 786 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 787 "throttle_trigger_threshold", 788 "an integer in the range of 1 to 100"); 789 return false; 790 } 791 792 if (params->has_cpu_throttle_initial && 793 (params->cpu_throttle_initial < 1 || 794 params->cpu_throttle_initial > 99)) { 795 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 796 "cpu_throttle_initial", 797 "an integer in the range of 1 to 99"); 798 return false; 799 } 800 801 if (params->has_cpu_throttle_increment && 802 (params->cpu_throttle_increment < 1 || 803 params->cpu_throttle_increment > 99)) { 804 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 805 "cpu_throttle_increment", 806 "an integer in the range of 1 to 99"); 807 return false; 808 } 809 810 if (params->has_max_bandwidth && (params->max_bandwidth > SIZE_MAX)) { 811 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 812 "max_bandwidth", 813 "an integer in the range of 0 to "stringify(SIZE_MAX) 814 " bytes/second"); 815 return false; 816 } 817 818 if (params->has_downtime_limit && 819 (params->downtime_limit > MAX_MIGRATE_DOWNTIME)) { 820 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 821 "downtime_limit", 822 "an integer in the range of 0 to " 823 stringify(MAX_MIGRATE_DOWNTIME)" ms"); 824 return false; 825 } 826 827 /* x_checkpoint_delay is now always positive */ 828 829 if (params->has_multifd_channels && (params->multifd_channels < 1)) { 830 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 831 "multifd_channels", 832 "a value between 1 and 255"); 833 return false; 834 } 835 836 if (params->has_multifd_zlib_level && 837 (params->multifd_zlib_level > 9)) { 838 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "multifd_zlib_level", 839 "a value between 0 and 9"); 840 return false; 841 } 842 843 if (params->has_multifd_zstd_level && 844 (params->multifd_zstd_level > 20)) { 845 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "multifd_zstd_level", 846 "a value between 0 and 20"); 847 return false; 848 } 849 850 if (params->has_xbzrle_cache_size && 851 (params->xbzrle_cache_size < qemu_target_page_size() || 852 !is_power_of_2(params->xbzrle_cache_size))) { 853 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 854 "xbzrle_cache_size", 855 "a power of two no less than the target page size"); 856 return false; 857 } 858 859 if (params->has_max_cpu_throttle && 860 (params->max_cpu_throttle < params->cpu_throttle_initial || 861 params->max_cpu_throttle > 99)) { 862 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 863 "max_cpu_throttle", 864 "an integer in the range of cpu_throttle_initial to 99"); 865 return false; 866 } 867 868 if (params->has_announce_initial && 869 params->announce_initial > 100000) { 870 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 871 "announce_initial", 872 "a value between 0 and 100000"); 873 return false; 874 } 875 if (params->has_announce_max && 876 params->announce_max > 100000) { 877 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 878 "announce_max", 879 "a value between 0 and 100000"); 880 return false; 881 } 882 if (params->has_announce_rounds && 883 params->announce_rounds > 1000) { 884 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 885 "announce_rounds", 886 "a value between 0 and 1000"); 887 return false; 888 } 889 if (params->has_announce_step && 890 (params->announce_step < 1 || 891 params->announce_step > 10000)) { 892 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 893 "announce_step", 894 "a value between 0 and 10000"); 895 return false; 896 } 897 898 if (params->has_block_bitmap_mapping && 899 !check_dirty_bitmap_mig_alias_map(params->block_bitmap_mapping, errp)) { 900 error_prepend(errp, "Invalid mapping given for block-bitmap-mapping: "); 901 return false; 902 } 903 904 #ifdef CONFIG_LINUX 905 if (migrate_zero_copy_send() && 906 ((params->has_multifd_compression && params->multifd_compression) || 907 (params->tls_creds && *params->tls_creds))) { 908 error_setg(errp, 909 "Zero copy only available for non-compressed non-TLS multifd migration"); 910 return false; 911 } 912 #endif 913 914 return true; 915 } 916 917 static void migrate_params_test_apply(MigrateSetParameters *params, 918 MigrationParameters *dest) 919 { 920 *dest = migrate_get_current()->parameters; 921 922 /* TODO use QAPI_CLONE() instead of duplicating it inline */ 923 924 if (params->has_compress_level) { 925 dest->compress_level = params->compress_level; 926 } 927 928 if (params->has_compress_threads) { 929 dest->compress_threads = params->compress_threads; 930 } 931 932 if (params->has_compress_wait_thread) { 933 dest->compress_wait_thread = params->compress_wait_thread; 934 } 935 936 if (params->has_decompress_threads) { 937 dest->decompress_threads = params->decompress_threads; 938 } 939 940 if (params->has_throttle_trigger_threshold) { 941 dest->throttle_trigger_threshold = params->throttle_trigger_threshold; 942 } 943 944 if (params->has_cpu_throttle_initial) { 945 dest->cpu_throttle_initial = params->cpu_throttle_initial; 946 } 947 948 if (params->has_cpu_throttle_increment) { 949 dest->cpu_throttle_increment = params->cpu_throttle_increment; 950 } 951 952 if (params->has_cpu_throttle_tailslow) { 953 dest->cpu_throttle_tailslow = params->cpu_throttle_tailslow; 954 } 955 956 if (params->tls_creds) { 957 assert(params->tls_creds->type == QTYPE_QSTRING); 958 dest->tls_creds = params->tls_creds->u.s; 959 } 960 961 if (params->tls_hostname) { 962 assert(params->tls_hostname->type == QTYPE_QSTRING); 963 dest->tls_hostname = params->tls_hostname->u.s; 964 } 965 966 if (params->has_max_bandwidth) { 967 dest->max_bandwidth = params->max_bandwidth; 968 } 969 970 if (params->has_downtime_limit) { 971 dest->downtime_limit = params->downtime_limit; 972 } 973 974 if (params->has_x_checkpoint_delay) { 975 dest->x_checkpoint_delay = params->x_checkpoint_delay; 976 } 977 978 if (params->has_block_incremental) { 979 dest->block_incremental = params->block_incremental; 980 } 981 if (params->has_multifd_channels) { 982 dest->multifd_channels = params->multifd_channels; 983 } 984 if (params->has_multifd_compression) { 985 dest->multifd_compression = params->multifd_compression; 986 } 987 if (params->has_xbzrle_cache_size) { 988 dest->xbzrle_cache_size = params->xbzrle_cache_size; 989 } 990 if (params->has_max_postcopy_bandwidth) { 991 dest->max_postcopy_bandwidth = params->max_postcopy_bandwidth; 992 } 993 if (params->has_max_cpu_throttle) { 994 dest->max_cpu_throttle = params->max_cpu_throttle; 995 } 996 if (params->has_announce_initial) { 997 dest->announce_initial = params->announce_initial; 998 } 999 if (params->has_announce_max) { 1000 dest->announce_max = params->announce_max; 1001 } 1002 if (params->has_announce_rounds) { 1003 dest->announce_rounds = params->announce_rounds; 1004 } 1005 if (params->has_announce_step) { 1006 dest->announce_step = params->announce_step; 1007 } 1008 1009 if (params->has_block_bitmap_mapping) { 1010 dest->has_block_bitmap_mapping = true; 1011 dest->block_bitmap_mapping = params->block_bitmap_mapping; 1012 } 1013 } 1014 1015 static void migrate_params_apply(MigrateSetParameters *params, Error **errp) 1016 { 1017 MigrationState *s = migrate_get_current(); 1018 1019 /* TODO use QAPI_CLONE() instead of duplicating it inline */ 1020 1021 if (params->has_compress_level) { 1022 s->parameters.compress_level = params->compress_level; 1023 } 1024 1025 if (params->has_compress_threads) { 1026 s->parameters.compress_threads = params->compress_threads; 1027 } 1028 1029 if (params->has_compress_wait_thread) { 1030 s->parameters.compress_wait_thread = params->compress_wait_thread; 1031 } 1032 1033 if (params->has_decompress_threads) { 1034 s->parameters.decompress_threads = params->decompress_threads; 1035 } 1036 1037 if (params->has_throttle_trigger_threshold) { 1038 s->parameters.throttle_trigger_threshold = params->throttle_trigger_threshold; 1039 } 1040 1041 if (params->has_cpu_throttle_initial) { 1042 s->parameters.cpu_throttle_initial = params->cpu_throttle_initial; 1043 } 1044 1045 if (params->has_cpu_throttle_increment) { 1046 s->parameters.cpu_throttle_increment = params->cpu_throttle_increment; 1047 } 1048 1049 if (params->has_cpu_throttle_tailslow) { 1050 s->parameters.cpu_throttle_tailslow = params->cpu_throttle_tailslow; 1051 } 1052 1053 if (params->tls_creds) { 1054 g_free(s->parameters.tls_creds); 1055 assert(params->tls_creds->type == QTYPE_QSTRING); 1056 s->parameters.tls_creds = g_strdup(params->tls_creds->u.s); 1057 } 1058 1059 if (params->tls_hostname) { 1060 g_free(s->parameters.tls_hostname); 1061 assert(params->tls_hostname->type == QTYPE_QSTRING); 1062 s->parameters.tls_hostname = g_strdup(params->tls_hostname->u.s); 1063 } 1064 1065 if (params->tls_authz) { 1066 g_free(s->parameters.tls_authz); 1067 assert(params->tls_authz->type == QTYPE_QSTRING); 1068 s->parameters.tls_authz = g_strdup(params->tls_authz->u.s); 1069 } 1070 1071 if (params->has_max_bandwidth) { 1072 s->parameters.max_bandwidth = params->max_bandwidth; 1073 if (s->to_dst_file && !migration_in_postcopy()) { 1074 qemu_file_set_rate_limit(s->to_dst_file, 1075 s->parameters.max_bandwidth / XFER_LIMIT_RATIO); 1076 } 1077 } 1078 1079 if (params->has_downtime_limit) { 1080 s->parameters.downtime_limit = params->downtime_limit; 1081 } 1082 1083 if (params->has_x_checkpoint_delay) { 1084 s->parameters.x_checkpoint_delay = params->x_checkpoint_delay; 1085 if (migration_in_colo_state()) { 1086 colo_checkpoint_notify(s); 1087 } 1088 } 1089 1090 if (params->has_block_incremental) { 1091 s->parameters.block_incremental = params->block_incremental; 1092 } 1093 if (params->has_multifd_channels) { 1094 s->parameters.multifd_channels = params->multifd_channels; 1095 } 1096 if (params->has_multifd_compression) { 1097 s->parameters.multifd_compression = params->multifd_compression; 1098 } 1099 if (params->has_xbzrle_cache_size) { 1100 s->parameters.xbzrle_cache_size = params->xbzrle_cache_size; 1101 xbzrle_cache_resize(params->xbzrle_cache_size, errp); 1102 } 1103 if (params->has_max_postcopy_bandwidth) { 1104 s->parameters.max_postcopy_bandwidth = params->max_postcopy_bandwidth; 1105 if (s->to_dst_file && migration_in_postcopy()) { 1106 qemu_file_set_rate_limit(s->to_dst_file, 1107 s->parameters.max_postcopy_bandwidth / XFER_LIMIT_RATIO); 1108 } 1109 } 1110 if (params->has_max_cpu_throttle) { 1111 s->parameters.max_cpu_throttle = params->max_cpu_throttle; 1112 } 1113 if (params->has_announce_initial) { 1114 s->parameters.announce_initial = params->announce_initial; 1115 } 1116 if (params->has_announce_max) { 1117 s->parameters.announce_max = params->announce_max; 1118 } 1119 if (params->has_announce_rounds) { 1120 s->parameters.announce_rounds = params->announce_rounds; 1121 } 1122 if (params->has_announce_step) { 1123 s->parameters.announce_step = params->announce_step; 1124 } 1125 1126 if (params->has_block_bitmap_mapping) { 1127 qapi_free_BitmapMigrationNodeAliasList( 1128 s->parameters.block_bitmap_mapping); 1129 1130 s->parameters.has_block_bitmap_mapping = true; 1131 s->parameters.block_bitmap_mapping = 1132 QAPI_CLONE(BitmapMigrationNodeAliasList, 1133 params->block_bitmap_mapping); 1134 } 1135 } 1136 1137 void qmp_migrate_set_parameters(MigrateSetParameters *params, Error **errp) 1138 { 1139 MigrationParameters tmp; 1140 1141 /* TODO Rewrite "" to null instead */ 1142 if (params->tls_creds 1143 && params->tls_creds->type == QTYPE_QNULL) { 1144 qobject_unref(params->tls_creds->u.n); 1145 params->tls_creds->type = QTYPE_QSTRING; 1146 params->tls_creds->u.s = strdup(""); 1147 } 1148 /* TODO Rewrite "" to null instead */ 1149 if (params->tls_hostname 1150 && params->tls_hostname->type == QTYPE_QNULL) { 1151 qobject_unref(params->tls_hostname->u.n); 1152 params->tls_hostname->type = QTYPE_QSTRING; 1153 params->tls_hostname->u.s = strdup(""); 1154 } 1155 1156 migrate_params_test_apply(params, &tmp); 1157 1158 if (!migrate_params_check(&tmp, errp)) { 1159 /* Invalid parameter */ 1160 return; 1161 } 1162 1163 migrate_params_apply(params, errp); 1164 } 1165