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 /* 745 * Check whether the parameters are valid. Error will be put into errp 746 * (if provided). Return true if valid, otherwise false. 747 */ 748 bool migrate_params_check(MigrationParameters *params, Error **errp) 749 { 750 if (params->has_compress_level && 751 (params->compress_level > 9)) { 752 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "compress_level", 753 "a value between 0 and 9"); 754 return false; 755 } 756 757 if (params->has_compress_threads && (params->compress_threads < 1)) { 758 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 759 "compress_threads", 760 "a value between 1 and 255"); 761 return false; 762 } 763 764 if (params->has_decompress_threads && (params->decompress_threads < 1)) { 765 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 766 "decompress_threads", 767 "a value between 1 and 255"); 768 return false; 769 } 770 771 if (params->has_throttle_trigger_threshold && 772 (params->throttle_trigger_threshold < 1 || 773 params->throttle_trigger_threshold > 100)) { 774 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 775 "throttle_trigger_threshold", 776 "an integer in the range of 1 to 100"); 777 return false; 778 } 779 780 if (params->has_cpu_throttle_initial && 781 (params->cpu_throttle_initial < 1 || 782 params->cpu_throttle_initial > 99)) { 783 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 784 "cpu_throttle_initial", 785 "an integer in the range of 1 to 99"); 786 return false; 787 } 788 789 if (params->has_cpu_throttle_increment && 790 (params->cpu_throttle_increment < 1 || 791 params->cpu_throttle_increment > 99)) { 792 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 793 "cpu_throttle_increment", 794 "an integer in the range of 1 to 99"); 795 return false; 796 } 797 798 if (params->has_max_bandwidth && (params->max_bandwidth > SIZE_MAX)) { 799 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 800 "max_bandwidth", 801 "an integer in the range of 0 to "stringify(SIZE_MAX) 802 " bytes/second"); 803 return false; 804 } 805 806 if (params->has_downtime_limit && 807 (params->downtime_limit > MAX_MIGRATE_DOWNTIME)) { 808 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 809 "downtime_limit", 810 "an integer in the range of 0 to " 811 stringify(MAX_MIGRATE_DOWNTIME)" ms"); 812 return false; 813 } 814 815 /* x_checkpoint_delay is now always positive */ 816 817 if (params->has_multifd_channels && (params->multifd_channels < 1)) { 818 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 819 "multifd_channels", 820 "a value between 1 and 255"); 821 return false; 822 } 823 824 if (params->has_multifd_zlib_level && 825 (params->multifd_zlib_level > 9)) { 826 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "multifd_zlib_level", 827 "a value between 0 and 9"); 828 return false; 829 } 830 831 if (params->has_multifd_zstd_level && 832 (params->multifd_zstd_level > 20)) { 833 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "multifd_zstd_level", 834 "a value between 0 and 20"); 835 return false; 836 } 837 838 if (params->has_xbzrle_cache_size && 839 (params->xbzrle_cache_size < qemu_target_page_size() || 840 !is_power_of_2(params->xbzrle_cache_size))) { 841 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 842 "xbzrle_cache_size", 843 "a power of two no less than the target page size"); 844 return false; 845 } 846 847 if (params->has_max_cpu_throttle && 848 (params->max_cpu_throttle < params->cpu_throttle_initial || 849 params->max_cpu_throttle > 99)) { 850 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 851 "max_cpu_throttle", 852 "an integer in the range of cpu_throttle_initial to 99"); 853 return false; 854 } 855 856 if (params->has_announce_initial && 857 params->announce_initial > 100000) { 858 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 859 "announce_initial", 860 "a value between 0 and 100000"); 861 return false; 862 } 863 if (params->has_announce_max && 864 params->announce_max > 100000) { 865 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 866 "announce_max", 867 "a value between 0 and 100000"); 868 return false; 869 } 870 if (params->has_announce_rounds && 871 params->announce_rounds > 1000) { 872 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 873 "announce_rounds", 874 "a value between 0 and 1000"); 875 return false; 876 } 877 if (params->has_announce_step && 878 (params->announce_step < 1 || 879 params->announce_step > 10000)) { 880 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 881 "announce_step", 882 "a value between 0 and 10000"); 883 return false; 884 } 885 886 if (params->has_block_bitmap_mapping && 887 !check_dirty_bitmap_mig_alias_map(params->block_bitmap_mapping, errp)) { 888 error_prepend(errp, "Invalid mapping given for block-bitmap-mapping: "); 889 return false; 890 } 891 892 #ifdef CONFIG_LINUX 893 if (migrate_zero_copy_send() && 894 ((params->has_multifd_compression && params->multifd_compression) || 895 (params->tls_creds && *params->tls_creds))) { 896 error_setg(errp, 897 "Zero copy only available for non-compressed non-TLS multifd migration"); 898 return false; 899 } 900 #endif 901 902 return true; 903 } 904 905 static void migrate_params_test_apply(MigrateSetParameters *params, 906 MigrationParameters *dest) 907 { 908 *dest = migrate_get_current()->parameters; 909 910 /* TODO use QAPI_CLONE() instead of duplicating it inline */ 911 912 if (params->has_compress_level) { 913 dest->compress_level = params->compress_level; 914 } 915 916 if (params->has_compress_threads) { 917 dest->compress_threads = params->compress_threads; 918 } 919 920 if (params->has_compress_wait_thread) { 921 dest->compress_wait_thread = params->compress_wait_thread; 922 } 923 924 if (params->has_decompress_threads) { 925 dest->decompress_threads = params->decompress_threads; 926 } 927 928 if (params->has_throttle_trigger_threshold) { 929 dest->throttle_trigger_threshold = params->throttle_trigger_threshold; 930 } 931 932 if (params->has_cpu_throttle_initial) { 933 dest->cpu_throttle_initial = params->cpu_throttle_initial; 934 } 935 936 if (params->has_cpu_throttle_increment) { 937 dest->cpu_throttle_increment = params->cpu_throttle_increment; 938 } 939 940 if (params->has_cpu_throttle_tailslow) { 941 dest->cpu_throttle_tailslow = params->cpu_throttle_tailslow; 942 } 943 944 if (params->tls_creds) { 945 assert(params->tls_creds->type == QTYPE_QSTRING); 946 dest->tls_creds = params->tls_creds->u.s; 947 } 948 949 if (params->tls_hostname) { 950 assert(params->tls_hostname->type == QTYPE_QSTRING); 951 dest->tls_hostname = params->tls_hostname->u.s; 952 } 953 954 if (params->has_max_bandwidth) { 955 dest->max_bandwidth = params->max_bandwidth; 956 } 957 958 if (params->has_downtime_limit) { 959 dest->downtime_limit = params->downtime_limit; 960 } 961 962 if (params->has_x_checkpoint_delay) { 963 dest->x_checkpoint_delay = params->x_checkpoint_delay; 964 } 965 966 if (params->has_block_incremental) { 967 dest->block_incremental = params->block_incremental; 968 } 969 if (params->has_multifd_channels) { 970 dest->multifd_channels = params->multifd_channels; 971 } 972 if (params->has_multifd_compression) { 973 dest->multifd_compression = params->multifd_compression; 974 } 975 if (params->has_xbzrle_cache_size) { 976 dest->xbzrle_cache_size = params->xbzrle_cache_size; 977 } 978 if (params->has_max_postcopy_bandwidth) { 979 dest->max_postcopy_bandwidth = params->max_postcopy_bandwidth; 980 } 981 if (params->has_max_cpu_throttle) { 982 dest->max_cpu_throttle = params->max_cpu_throttle; 983 } 984 if (params->has_announce_initial) { 985 dest->announce_initial = params->announce_initial; 986 } 987 if (params->has_announce_max) { 988 dest->announce_max = params->announce_max; 989 } 990 if (params->has_announce_rounds) { 991 dest->announce_rounds = params->announce_rounds; 992 } 993 if (params->has_announce_step) { 994 dest->announce_step = params->announce_step; 995 } 996 997 if (params->has_block_bitmap_mapping) { 998 dest->has_block_bitmap_mapping = true; 999 dest->block_bitmap_mapping = params->block_bitmap_mapping; 1000 } 1001 } 1002 1003 static void migrate_params_apply(MigrateSetParameters *params, Error **errp) 1004 { 1005 MigrationState *s = migrate_get_current(); 1006 1007 /* TODO use QAPI_CLONE() instead of duplicating it inline */ 1008 1009 if (params->has_compress_level) { 1010 s->parameters.compress_level = params->compress_level; 1011 } 1012 1013 if (params->has_compress_threads) { 1014 s->parameters.compress_threads = params->compress_threads; 1015 } 1016 1017 if (params->has_compress_wait_thread) { 1018 s->parameters.compress_wait_thread = params->compress_wait_thread; 1019 } 1020 1021 if (params->has_decompress_threads) { 1022 s->parameters.decompress_threads = params->decompress_threads; 1023 } 1024 1025 if (params->has_throttle_trigger_threshold) { 1026 s->parameters.throttle_trigger_threshold = params->throttle_trigger_threshold; 1027 } 1028 1029 if (params->has_cpu_throttle_initial) { 1030 s->parameters.cpu_throttle_initial = params->cpu_throttle_initial; 1031 } 1032 1033 if (params->has_cpu_throttle_increment) { 1034 s->parameters.cpu_throttle_increment = params->cpu_throttle_increment; 1035 } 1036 1037 if (params->has_cpu_throttle_tailslow) { 1038 s->parameters.cpu_throttle_tailslow = params->cpu_throttle_tailslow; 1039 } 1040 1041 if (params->tls_creds) { 1042 g_free(s->parameters.tls_creds); 1043 assert(params->tls_creds->type == QTYPE_QSTRING); 1044 s->parameters.tls_creds = g_strdup(params->tls_creds->u.s); 1045 } 1046 1047 if (params->tls_hostname) { 1048 g_free(s->parameters.tls_hostname); 1049 assert(params->tls_hostname->type == QTYPE_QSTRING); 1050 s->parameters.tls_hostname = g_strdup(params->tls_hostname->u.s); 1051 } 1052 1053 if (params->tls_authz) { 1054 g_free(s->parameters.tls_authz); 1055 assert(params->tls_authz->type == QTYPE_QSTRING); 1056 s->parameters.tls_authz = g_strdup(params->tls_authz->u.s); 1057 } 1058 1059 if (params->has_max_bandwidth) { 1060 s->parameters.max_bandwidth = params->max_bandwidth; 1061 if (s->to_dst_file && !migration_in_postcopy()) { 1062 qemu_file_set_rate_limit(s->to_dst_file, 1063 s->parameters.max_bandwidth / XFER_LIMIT_RATIO); 1064 } 1065 } 1066 1067 if (params->has_downtime_limit) { 1068 s->parameters.downtime_limit = params->downtime_limit; 1069 } 1070 1071 if (params->has_x_checkpoint_delay) { 1072 s->parameters.x_checkpoint_delay = params->x_checkpoint_delay; 1073 if (migration_in_colo_state()) { 1074 colo_checkpoint_notify(s); 1075 } 1076 } 1077 1078 if (params->has_block_incremental) { 1079 s->parameters.block_incremental = params->block_incremental; 1080 } 1081 if (params->has_multifd_channels) { 1082 s->parameters.multifd_channels = params->multifd_channels; 1083 } 1084 if (params->has_multifd_compression) { 1085 s->parameters.multifd_compression = params->multifd_compression; 1086 } 1087 if (params->has_xbzrle_cache_size) { 1088 s->parameters.xbzrle_cache_size = params->xbzrle_cache_size; 1089 xbzrle_cache_resize(params->xbzrle_cache_size, errp); 1090 } 1091 if (params->has_max_postcopy_bandwidth) { 1092 s->parameters.max_postcopy_bandwidth = params->max_postcopy_bandwidth; 1093 if (s->to_dst_file && migration_in_postcopy()) { 1094 qemu_file_set_rate_limit(s->to_dst_file, 1095 s->parameters.max_postcopy_bandwidth / XFER_LIMIT_RATIO); 1096 } 1097 } 1098 if (params->has_max_cpu_throttle) { 1099 s->parameters.max_cpu_throttle = params->max_cpu_throttle; 1100 } 1101 if (params->has_announce_initial) { 1102 s->parameters.announce_initial = params->announce_initial; 1103 } 1104 if (params->has_announce_max) { 1105 s->parameters.announce_max = params->announce_max; 1106 } 1107 if (params->has_announce_rounds) { 1108 s->parameters.announce_rounds = params->announce_rounds; 1109 } 1110 if (params->has_announce_step) { 1111 s->parameters.announce_step = params->announce_step; 1112 } 1113 1114 if (params->has_block_bitmap_mapping) { 1115 qapi_free_BitmapMigrationNodeAliasList( 1116 s->parameters.block_bitmap_mapping); 1117 1118 s->parameters.has_block_bitmap_mapping = true; 1119 s->parameters.block_bitmap_mapping = 1120 QAPI_CLONE(BitmapMigrationNodeAliasList, 1121 params->block_bitmap_mapping); 1122 } 1123 } 1124 1125 void qmp_migrate_set_parameters(MigrateSetParameters *params, Error **errp) 1126 { 1127 MigrationParameters tmp; 1128 1129 /* TODO Rewrite "" to null instead */ 1130 if (params->tls_creds 1131 && params->tls_creds->type == QTYPE_QNULL) { 1132 qobject_unref(params->tls_creds->u.n); 1133 params->tls_creds->type = QTYPE_QSTRING; 1134 params->tls_creds->u.s = strdup(""); 1135 } 1136 /* TODO Rewrite "" to null instead */ 1137 if (params->tls_hostname 1138 && params->tls_hostname->type == QTYPE_QNULL) { 1139 qobject_unref(params->tls_hostname->u.n); 1140 params->tls_hostname->type = QTYPE_QSTRING; 1141 params->tls_hostname->u.s = strdup(""); 1142 } 1143 1144 migrate_params_test_apply(params, &tmp); 1145 1146 if (!migrate_params_check(&tmp, errp)) { 1147 /* Invalid parameter */ 1148 return; 1149 } 1150 1151 migrate_params_apply(params, errp); 1152 } 1153