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