|
@@ -63,7 +63,7 @@
|
|
|
#include "sysemu/cpus.h"
|
|
|
#include "yank_functions.h"
|
|
|
#include "sysemu/qtest.h"
|
|
|
-#include "ui/qemu-spice.h"
|
|
|
+#include "options.h"
|
|
|
|
|
|
#define MAX_THROTTLE (128 << 20) /* Migration transfer speed throttling */
|
|
|
|
|
@@ -136,39 +136,6 @@ enum mig_rp_message_type {
|
|
|
MIG_RP_MSG_MAX
|
|
|
};
|
|
|
|
|
|
-/* Migration capabilities set */
|
|
|
-struct MigrateCapsSet {
|
|
|
- int size; /* Capability set size */
|
|
|
- MigrationCapability caps[]; /* Variadic array of capabilities */
|
|
|
-};
|
|
|
-typedef struct MigrateCapsSet MigrateCapsSet;
|
|
|
-
|
|
|
-/* Define and initialize MigrateCapsSet */
|
|
|
-#define INITIALIZE_MIGRATE_CAPS_SET(_name, ...) \
|
|
|
- MigrateCapsSet _name = { \
|
|
|
- .size = sizeof((int []) { __VA_ARGS__ }) / sizeof(int), \
|
|
|
- .caps = { __VA_ARGS__ } \
|
|
|
- }
|
|
|
-
|
|
|
-/* Background-snapshot compatibility check list */
|
|
|
-static const
|
|
|
-INITIALIZE_MIGRATE_CAPS_SET(check_caps_background_snapshot,
|
|
|
- MIGRATION_CAPABILITY_POSTCOPY_RAM,
|
|
|
- MIGRATION_CAPABILITY_DIRTY_BITMAPS,
|
|
|
- MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME,
|
|
|
- MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE,
|
|
|
- MIGRATION_CAPABILITY_RETURN_PATH,
|
|
|
- MIGRATION_CAPABILITY_MULTIFD,
|
|
|
- MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER,
|
|
|
- MIGRATION_CAPABILITY_AUTO_CONVERGE,
|
|
|
- MIGRATION_CAPABILITY_RELEASE_RAM,
|
|
|
- MIGRATION_CAPABILITY_RDMA_PIN_ALL,
|
|
|
- MIGRATION_CAPABILITY_COMPRESS,
|
|
|
- MIGRATION_CAPABILITY_XBZRLE,
|
|
|
- MIGRATION_CAPABILITY_X_COLO,
|
|
|
- MIGRATION_CAPABILITY_VALIDATE_UUID,
|
|
|
- MIGRATION_CAPABILITY_ZERO_COPY_SEND);
|
|
|
-
|
|
|
/* When we add fault tolerance, we could have several
|
|
|
migrations at once. For now we don't need to add
|
|
|
dynamic creation of migration */
|
|
@@ -186,7 +153,7 @@ static void migrate_fd_cancel(MigrationState *s);
|
|
|
|
|
|
static bool migration_needs_multiple_sockets(void)
|
|
|
{
|
|
|
- return migrate_use_multifd() || migrate_postcopy_preempt();
|
|
|
+ return migrate_multifd() || migrate_postcopy_preempt();
|
|
|
}
|
|
|
|
|
|
static bool uri_supports_multi_channels(const char *uri)
|
|
@@ -353,20 +320,11 @@ void migration_incoming_state_destroy(void)
|
|
|
|
|
|
static void migrate_generate_event(int new_state)
|
|
|
{
|
|
|
- if (migrate_use_events()) {
|
|
|
+ if (migrate_events()) {
|
|
|
qapi_event_send_migration(new_state);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static bool migrate_late_block_activate(void)
|
|
|
-{
|
|
|
- MigrationState *s;
|
|
|
-
|
|
|
- s = migrate_get_current();
|
|
|
-
|
|
|
- return s->capabilities[MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE];
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* Send a message on the return channel back to the source
|
|
|
* of the migration.
|
|
@@ -741,7 +699,7 @@ void migration_fd_process_incoming(QEMUFile *f, Error **errp)
|
|
|
static bool migration_should_start_incoming(bool main_channel)
|
|
|
{
|
|
|
/* Multifd doesn't start unless all channels are established */
|
|
|
- if (migrate_use_multifd()) {
|
|
|
+ if (migrate_multifd()) {
|
|
|
return migration_has_all_channels();
|
|
|
}
|
|
|
|
|
@@ -768,7 +726,7 @@ void migration_ioc_process_incoming(QIOChannel *ioc, Error **errp)
|
|
|
uint32_t channel_magic = 0;
|
|
|
int ret = 0;
|
|
|
|
|
|
- if (migrate_use_multifd() && !migrate_postcopy_ram() &&
|
|
|
+ if (migrate_multifd() && !migrate_postcopy_ram() &&
|
|
|
qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_READ_MSG_PEEK)) {
|
|
|
/*
|
|
|
* With multiple channels, it is possible that we receive channels
|
|
@@ -807,7 +765,7 @@ void migration_ioc_process_incoming(QIOChannel *ioc, Error **errp)
|
|
|
} else {
|
|
|
/* Multiple connections */
|
|
|
assert(migration_needs_multiple_sockets());
|
|
|
- if (migrate_use_multifd()) {
|
|
|
+ if (migrate_multifd()) {
|
|
|
multifd_recv_new_channel(ioc, &local_err);
|
|
|
} else {
|
|
|
assert(migrate_postcopy_preempt());
|
|
@@ -843,7 +801,7 @@ bool migration_has_all_channels(void)
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- if (migrate_use_multifd()) {
|
|
|
+ if (migrate_multifd()) {
|
|
|
return multifd_recv_all_channels_created();
|
|
|
}
|
|
|
|
|
@@ -928,139 +886,6 @@ void migrate_send_rp_resume_ack(MigrationIncomingState *mis, uint32_t value)
|
|
|
migrate_send_rp_message(mis, MIG_RP_MSG_RESUME_ACK, sizeof(buf), &buf);
|
|
|
}
|
|
|
|
|
|
-MigrationCapabilityStatusList *qmp_query_migrate_capabilities(Error **errp)
|
|
|
-{
|
|
|
- MigrationCapabilityStatusList *head = NULL, **tail = &head;
|
|
|
- MigrationCapabilityStatus *caps;
|
|
|
- MigrationState *s = migrate_get_current();
|
|
|
- int i;
|
|
|
-
|
|
|
- for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
|
|
|
-#ifndef CONFIG_LIVE_BLOCK_MIGRATION
|
|
|
- if (i == MIGRATION_CAPABILITY_BLOCK) {
|
|
|
- continue;
|
|
|
- }
|
|
|
-#endif
|
|
|
- caps = g_malloc0(sizeof(*caps));
|
|
|
- caps->capability = i;
|
|
|
- caps->state = s->capabilities[i];
|
|
|
- QAPI_LIST_APPEND(tail, caps);
|
|
|
- }
|
|
|
-
|
|
|
- return head;
|
|
|
-}
|
|
|
-
|
|
|
-MigrationParameters *qmp_query_migrate_parameters(Error **errp)
|
|
|
-{
|
|
|
- MigrationParameters *params;
|
|
|
- MigrationState *s = migrate_get_current();
|
|
|
-
|
|
|
- /* TODO use QAPI_CLONE() instead of duplicating it inline */
|
|
|
- params = g_malloc0(sizeof(*params));
|
|
|
- params->has_compress_level = true;
|
|
|
- params->compress_level = s->parameters.compress_level;
|
|
|
- params->has_compress_threads = true;
|
|
|
- params->compress_threads = s->parameters.compress_threads;
|
|
|
- params->has_compress_wait_thread = true;
|
|
|
- params->compress_wait_thread = s->parameters.compress_wait_thread;
|
|
|
- params->has_decompress_threads = true;
|
|
|
- params->decompress_threads = s->parameters.decompress_threads;
|
|
|
- params->has_throttle_trigger_threshold = true;
|
|
|
- params->throttle_trigger_threshold = s->parameters.throttle_trigger_threshold;
|
|
|
- params->has_cpu_throttle_initial = true;
|
|
|
- params->cpu_throttle_initial = s->parameters.cpu_throttle_initial;
|
|
|
- params->has_cpu_throttle_increment = true;
|
|
|
- params->cpu_throttle_increment = s->parameters.cpu_throttle_increment;
|
|
|
- params->has_cpu_throttle_tailslow = true;
|
|
|
- params->cpu_throttle_tailslow = s->parameters.cpu_throttle_tailslow;
|
|
|
- params->tls_creds = g_strdup(s->parameters.tls_creds);
|
|
|
- params->tls_hostname = g_strdup(s->parameters.tls_hostname);
|
|
|
- params->tls_authz = g_strdup(s->parameters.tls_authz ?
|
|
|
- s->parameters.tls_authz : "");
|
|
|
- params->has_max_bandwidth = true;
|
|
|
- params->max_bandwidth = s->parameters.max_bandwidth;
|
|
|
- params->has_downtime_limit = true;
|
|
|
- params->downtime_limit = s->parameters.downtime_limit;
|
|
|
- params->has_x_checkpoint_delay = true;
|
|
|
- params->x_checkpoint_delay = s->parameters.x_checkpoint_delay;
|
|
|
- params->has_block_incremental = true;
|
|
|
- params->block_incremental = s->parameters.block_incremental;
|
|
|
- params->has_multifd_channels = true;
|
|
|
- params->multifd_channels = s->parameters.multifd_channels;
|
|
|
- params->has_multifd_compression = true;
|
|
|
- params->multifd_compression = s->parameters.multifd_compression;
|
|
|
- params->has_multifd_zlib_level = true;
|
|
|
- params->multifd_zlib_level = s->parameters.multifd_zlib_level;
|
|
|
- params->has_multifd_zstd_level = true;
|
|
|
- params->multifd_zstd_level = s->parameters.multifd_zstd_level;
|
|
|
- params->has_xbzrle_cache_size = true;
|
|
|
- params->xbzrle_cache_size = s->parameters.xbzrle_cache_size;
|
|
|
- params->has_max_postcopy_bandwidth = true;
|
|
|
- params->max_postcopy_bandwidth = s->parameters.max_postcopy_bandwidth;
|
|
|
- params->has_max_cpu_throttle = true;
|
|
|
- params->max_cpu_throttle = s->parameters.max_cpu_throttle;
|
|
|
- params->has_announce_initial = true;
|
|
|
- params->announce_initial = s->parameters.announce_initial;
|
|
|
- params->has_announce_max = true;
|
|
|
- params->announce_max = s->parameters.announce_max;
|
|
|
- params->has_announce_rounds = true;
|
|
|
- params->announce_rounds = s->parameters.announce_rounds;
|
|
|
- params->has_announce_step = true;
|
|
|
- params->announce_step = s->parameters.announce_step;
|
|
|
-
|
|
|
- if (s->parameters.has_block_bitmap_mapping) {
|
|
|
- params->has_block_bitmap_mapping = true;
|
|
|
- params->block_bitmap_mapping =
|
|
|
- QAPI_CLONE(BitmapMigrationNodeAliasList,
|
|
|
- s->parameters.block_bitmap_mapping);
|
|
|
- }
|
|
|
-
|
|
|
- return params;
|
|
|
-}
|
|
|
-
|
|
|
-void qmp_client_migrate_info(const char *protocol, const char *hostname,
|
|
|
- bool has_port, int64_t port,
|
|
|
- bool has_tls_port, int64_t tls_port,
|
|
|
- const char *cert_subject,
|
|
|
- Error **errp)
|
|
|
-{
|
|
|
- if (strcmp(protocol, "spice") == 0) {
|
|
|
- if (!qemu_using_spice(errp)) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- if (!has_port && !has_tls_port) {
|
|
|
- error_setg(errp, QERR_MISSING_PARAMETER, "port/tls-port");
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- if (qemu_spice.migrate_info(hostname,
|
|
|
- has_port ? port : -1,
|
|
|
- has_tls_port ? tls_port : -1,
|
|
|
- cert_subject)) {
|
|
|
- error_setg(errp, "Could not set up display for migration");
|
|
|
- return;
|
|
|
- }
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "protocol", "'spice'");
|
|
|
-}
|
|
|
-
|
|
|
-AnnounceParameters *migrate_announce_params(void)
|
|
|
-{
|
|
|
- static AnnounceParameters ap;
|
|
|
-
|
|
|
- MigrationState *s = migrate_get_current();
|
|
|
-
|
|
|
- ap.initial = s->parameters.announce_initial;
|
|
|
- ap.max = s->parameters.announce_max;
|
|
|
- ap.rounds = s->parameters.announce_rounds;
|
|
|
- ap.step = s->parameters.announce_step;
|
|
|
-
|
|
|
- return ≈
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* Return true if we're already in the middle of a migration
|
|
|
* (i.e. any of the active or setup states)
|
|
@@ -1160,7 +985,7 @@ static void populate_ram_info(MigrationInfo *info, MigrationState *s)
|
|
|
info->ram->downtime_bytes = stat64_get(&ram_counters.downtime_bytes);
|
|
|
info->ram->postcopy_bytes = stat64_get(&ram_counters.postcopy_bytes);
|
|
|
|
|
|
- if (migrate_use_xbzrle()) {
|
|
|
+ if (migrate_xbzrle()) {
|
|
|
info->xbzrle_cache = g_malloc0(sizeof(*info->xbzrle_cache));
|
|
|
info->xbzrle_cache->cache_size = migrate_xbzrle_cache_size();
|
|
|
info->xbzrle_cache->bytes = xbzrle_counters.bytes;
|
|
@@ -1171,7 +996,7 @@ static void populate_ram_info(MigrationInfo *info, MigrationState *s)
|
|
|
info->xbzrle_cache->overflow = xbzrle_counters.overflow;
|
|
|
}
|
|
|
|
|
|
- if (migrate_use_compression()) {
|
|
|
+ if (migrate_compress()) {
|
|
|
info->compression = g_malloc0(sizeof(*info->compression));
|
|
|
info->compression->pages = compression_counters.pages;
|
|
|
info->compression->busy = compression_counters.busy;
|
|
@@ -1273,163 +1098,6 @@ static void fill_source_migration_info(MigrationInfo *info)
|
|
|
info->status = state;
|
|
|
}
|
|
|
|
|
|
-typedef enum WriteTrackingSupport {
|
|
|
- WT_SUPPORT_UNKNOWN = 0,
|
|
|
- WT_SUPPORT_ABSENT,
|
|
|
- WT_SUPPORT_AVAILABLE,
|
|
|
- WT_SUPPORT_COMPATIBLE
|
|
|
-} WriteTrackingSupport;
|
|
|
-
|
|
|
-static
|
|
|
-WriteTrackingSupport migrate_query_write_tracking(void)
|
|
|
-{
|
|
|
- /* Check if kernel supports required UFFD features */
|
|
|
- if (!ram_write_tracking_available()) {
|
|
|
- return WT_SUPPORT_ABSENT;
|
|
|
- }
|
|
|
- /*
|
|
|
- * Check if current memory configuration is
|
|
|
- * compatible with required UFFD features.
|
|
|
- */
|
|
|
- if (!ram_write_tracking_compatible()) {
|
|
|
- return WT_SUPPORT_AVAILABLE;
|
|
|
- }
|
|
|
-
|
|
|
- return WT_SUPPORT_COMPATIBLE;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * @migration_caps_check - check capability compatibility
|
|
|
- *
|
|
|
- * @old_caps: old capability list
|
|
|
- * @new_caps: new capability list
|
|
|
- * @errp: set *errp if the check failed, with reason
|
|
|
- *
|
|
|
- * Returns true if check passed, otherwise false.
|
|
|
- */
|
|
|
-static bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp)
|
|
|
-{
|
|
|
- MigrationIncomingState *mis = migration_incoming_get_current();
|
|
|
-
|
|
|
-#ifndef CONFIG_LIVE_BLOCK_MIGRATION
|
|
|
- if (new_caps[MIGRATION_CAPABILITY_BLOCK]) {
|
|
|
- error_setg(errp, "QEMU compiled without old-style (blk/-b, inc/-i) "
|
|
|
- "block migration");
|
|
|
- error_append_hint(errp, "Use drive_mirror+NBD instead.\n");
|
|
|
- return false;
|
|
|
- }
|
|
|
-#endif
|
|
|
-
|
|
|
-#ifndef CONFIG_REPLICATION
|
|
|
- if (new_caps[MIGRATION_CAPABILITY_X_COLO]) {
|
|
|
- error_setg(errp, "QEMU compiled without replication module"
|
|
|
- " can't enable COLO");
|
|
|
- error_append_hint(errp, "Please enable replication before COLO.\n");
|
|
|
- return false;
|
|
|
- }
|
|
|
-#endif
|
|
|
-
|
|
|
- if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) {
|
|
|
- /* This check is reasonably expensive, so only when it's being
|
|
|
- * set the first time, also it's only the destination that needs
|
|
|
- * special support.
|
|
|
- */
|
|
|
- if (!old_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM] &&
|
|
|
- runstate_check(RUN_STATE_INMIGRATE) &&
|
|
|
- !postcopy_ram_supported_by_host(mis)) {
|
|
|
- /* postcopy_ram_supported_by_host will have emitted a more
|
|
|
- * detailed message
|
|
|
- */
|
|
|
- error_setg(errp, "Postcopy is not supported");
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- if (new_caps[MIGRATION_CAPABILITY_X_IGNORE_SHARED]) {
|
|
|
- error_setg(errp, "Postcopy is not compatible with ignore-shared");
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (new_caps[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT]) {
|
|
|
- WriteTrackingSupport wt_support;
|
|
|
- int idx;
|
|
|
- /*
|
|
|
- * Check if 'background-snapshot' capability is supported by
|
|
|
- * host kernel and compatible with guest memory configuration.
|
|
|
- */
|
|
|
- wt_support = migrate_query_write_tracking();
|
|
|
- if (wt_support < WT_SUPPORT_AVAILABLE) {
|
|
|
- error_setg(errp, "Background-snapshot is not supported by host kernel");
|
|
|
- return false;
|
|
|
- }
|
|
|
- if (wt_support < WT_SUPPORT_COMPATIBLE) {
|
|
|
- error_setg(errp, "Background-snapshot is not compatible "
|
|
|
- "with guest memory configuration");
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- /*
|
|
|
- * Check if there are any migration capabilities
|
|
|
- * incompatible with 'background-snapshot'.
|
|
|
- */
|
|
|
- for (idx = 0; idx < check_caps_background_snapshot.size; idx++) {
|
|
|
- int incomp_cap = check_caps_background_snapshot.caps[idx];
|
|
|
- if (new_caps[incomp_cap]) {
|
|
|
- error_setg(errp,
|
|
|
- "Background-snapshot is not compatible with %s",
|
|
|
- MigrationCapability_str(incomp_cap));
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-#ifdef CONFIG_LINUX
|
|
|
- if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND] &&
|
|
|
- (!new_caps[MIGRATION_CAPABILITY_MULTIFD] ||
|
|
|
- new_caps[MIGRATION_CAPABILITY_COMPRESS] ||
|
|
|
- new_caps[MIGRATION_CAPABILITY_XBZRLE] ||
|
|
|
- migrate_multifd_compression() ||
|
|
|
- migrate_use_tls())) {
|
|
|
- error_setg(errp,
|
|
|
- "Zero copy only available for non-compressed non-TLS multifd migration");
|
|
|
- return false;
|
|
|
- }
|
|
|
-#else
|
|
|
- if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND]) {
|
|
|
- error_setg(errp,
|
|
|
- "Zero copy currently only available on Linux");
|
|
|
- return false;
|
|
|
- }
|
|
|
-#endif
|
|
|
-
|
|
|
- if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT]) {
|
|
|
- if (!new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) {
|
|
|
- error_setg(errp, "Postcopy preempt requires postcopy-ram");
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- /*
|
|
|
- * Preempt mode requires urgent pages to be sent in separate
|
|
|
- * channel, OTOH compression logic will disorder all pages into
|
|
|
- * different compression channels, which is not compatible with the
|
|
|
- * preempt assumptions on channel assignments.
|
|
|
- */
|
|
|
- if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) {
|
|
|
- error_setg(errp, "Postcopy preempt not compatible with compress");
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) {
|
|
|
- if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) {
|
|
|
- error_setg(errp, "Multifd is not compatible with compress");
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
static void fill_destination_migration_info(MigrationInfo *info)
|
|
|
{
|
|
|
MigrationIncomingState *mis = migration_incoming_get_current();
|
|
@@ -1472,32 +1140,6 @@ MigrationInfo *qmp_query_migrate(Error **errp)
|
|
|
return info;
|
|
|
}
|
|
|
|
|
|
-void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params,
|
|
|
- Error **errp)
|
|
|
-{
|
|
|
- MigrationState *s = migrate_get_current();
|
|
|
- MigrationCapabilityStatusList *cap;
|
|
|
- bool new_caps[MIGRATION_CAPABILITY__MAX];
|
|
|
-
|
|
|
- if (migration_is_running(s->state)) {
|
|
|
- error_setg(errp, QERR_MIGRATION_ACTIVE);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- memcpy(new_caps, s->capabilities, sizeof(new_caps));
|
|
|
- for (cap = params; cap; cap = cap->next) {
|
|
|
- new_caps[cap->value->capability] = cap->value->state;
|
|
|
- }
|
|
|
-
|
|
|
- if (!migrate_caps_check(s->capabilities, new_caps, errp)) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- for (cap = params; cap; cap = cap->next) {
|
|
|
- s->capabilities[cap->value->capability] = cap->value->state;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* Check whether the parameters are valid. Error will be put into errp
|
|
|
* (if provided). Return true if valid, otherwise false.
|
|
@@ -1647,7 +1289,7 @@ static bool migrate_params_check(MigrationParameters *params, Error **errp)
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_LINUX
|
|
|
- if (migrate_use_zero_copy_send() &&
|
|
|
+ if (migrate_zero_copy_send() &&
|
|
|
((params->has_multifd_compression && params->multifd_compression) ||
|
|
|
(params->tls_creds && *params->tls_creds))) {
|
|
|
error_setg(errp,
|
|
@@ -1942,27 +1584,6 @@ void migrate_set_state(int *state, int old_state, int new_state)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static MigrationCapabilityStatus *migrate_cap_add(MigrationCapability index,
|
|
|
- bool state)
|
|
|
-{
|
|
|
- MigrationCapabilityStatus *cap;
|
|
|
-
|
|
|
- cap = g_new0(MigrationCapabilityStatus, 1);
|
|
|
- cap->capability = index;
|
|
|
- cap->state = state;
|
|
|
-
|
|
|
- return cap;
|
|
|
-}
|
|
|
-
|
|
|
-void migrate_set_block_enabled(bool value, Error **errp)
|
|
|
-{
|
|
|
- MigrationCapabilityStatusList *cap = NULL;
|
|
|
-
|
|
|
- QAPI_LIST_PREPEND(cap, migrate_cap_add(MIGRATION_CAPABILITY_BLOCK, value));
|
|
|
- qmp_migrate_set_capabilities(cap, errp);
|
|
|
- qapi_free_MigrationCapabilityStatusList(cap);
|
|
|
-}
|
|
|
-
|
|
|
static void migrate_set_block_incremental(MigrationState *s, bool value)
|
|
|
{
|
|
|
s->parameters.block_incremental = value;
|
|
@@ -1972,7 +1593,7 @@ static void block_cleanup_parameters(MigrationState *s)
|
|
|
{
|
|
|
if (s->must_remove_block_options) {
|
|
|
/* setting to false can never fail */
|
|
|
- migrate_set_block_enabled(false, &error_abort);
|
|
|
+ migrate_cap_set(MIGRATION_CAPABILITY_BLOCK, false, &error_abort);
|
|
|
migrate_set_block_incremental(s, false);
|
|
|
s->must_remove_block_options = false;
|
|
|
}
|
|
@@ -2450,17 +2071,16 @@ static bool migrate_prepare(MigrationState *s, bool blk, bool blk_inc,
|
|
|
}
|
|
|
|
|
|
if (blk || blk_inc) {
|
|
|
- if (migrate_colo_enabled()) {
|
|
|
+ if (migrate_colo()) {
|
|
|
error_setg(errp, "No disk migration is required in COLO mode");
|
|
|
return false;
|
|
|
}
|
|
|
- if (migrate_use_block() || migrate_use_block_incremental()) {
|
|
|
+ if (migrate_block() || migrate_block_incremental()) {
|
|
|
error_setg(errp, "Command options are incompatible with "
|
|
|
"current migration capabilities");
|
|
|
return false;
|
|
|
}
|
|
|
- migrate_set_block_enabled(true, &local_err);
|
|
|
- if (local_err) {
|
|
|
+ if (!migrate_cap_set(MIGRATION_CAPABILITY_BLOCK, true, &local_err)) {
|
|
|
error_propagate(errp, local_err);
|
|
|
return false;
|
|
|
}
|
|
@@ -2557,203 +2177,6 @@ void qmp_migrate_continue(MigrationStatus state, Error **errp)
|
|
|
qemu_sem_post(&s->pause_sem);
|
|
|
}
|
|
|
|
|
|
-bool migrate_release_ram(void)
|
|
|
-{
|
|
|
- MigrationState *s;
|
|
|
-
|
|
|
- s = migrate_get_current();
|
|
|
-
|
|
|
- return s->capabilities[MIGRATION_CAPABILITY_RELEASE_RAM];
|
|
|
-}
|
|
|
-
|
|
|
-bool migrate_postcopy_ram(void)
|
|
|
-{
|
|
|
- MigrationState *s;
|
|
|
-
|
|
|
- s = migrate_get_current();
|
|
|
-
|
|
|
- return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_RAM];
|
|
|
-}
|
|
|
-
|
|
|
-bool migrate_postcopy(void)
|
|
|
-{
|
|
|
- return migrate_postcopy_ram() || migrate_dirty_bitmaps();
|
|
|
-}
|
|
|
-
|
|
|
-bool migrate_auto_converge(void)
|
|
|
-{
|
|
|
- MigrationState *s;
|
|
|
-
|
|
|
- s = migrate_get_current();
|
|
|
-
|
|
|
- return s->capabilities[MIGRATION_CAPABILITY_AUTO_CONVERGE];
|
|
|
-}
|
|
|
-
|
|
|
-bool migrate_zero_blocks(void)
|
|
|
-{
|
|
|
- MigrationState *s;
|
|
|
-
|
|
|
- s = migrate_get_current();
|
|
|
-
|
|
|
- return s->capabilities[MIGRATION_CAPABILITY_ZERO_BLOCKS];
|
|
|
-}
|
|
|
-
|
|
|
-bool migrate_postcopy_blocktime(void)
|
|
|
-{
|
|
|
- MigrationState *s;
|
|
|
-
|
|
|
- s = migrate_get_current();
|
|
|
-
|
|
|
- return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME];
|
|
|
-}
|
|
|
-
|
|
|
-bool migrate_use_compression(void)
|
|
|
-{
|
|
|
- MigrationState *s;
|
|
|
-
|
|
|
- s = migrate_get_current();
|
|
|
-
|
|
|
- return s->capabilities[MIGRATION_CAPABILITY_COMPRESS];
|
|
|
-}
|
|
|
-
|
|
|
-int migrate_compress_level(void)
|
|
|
-{
|
|
|
- MigrationState *s;
|
|
|
-
|
|
|
- s = migrate_get_current();
|
|
|
-
|
|
|
- return s->parameters.compress_level;
|
|
|
-}
|
|
|
-
|
|
|
-int migrate_compress_threads(void)
|
|
|
-{
|
|
|
- MigrationState *s;
|
|
|
-
|
|
|
- s = migrate_get_current();
|
|
|
-
|
|
|
- return s->parameters.compress_threads;
|
|
|
-}
|
|
|
-
|
|
|
-int migrate_compress_wait_thread(void)
|
|
|
-{
|
|
|
- MigrationState *s;
|
|
|
-
|
|
|
- s = migrate_get_current();
|
|
|
-
|
|
|
- return s->parameters.compress_wait_thread;
|
|
|
-}
|
|
|
-
|
|
|
-int migrate_decompress_threads(void)
|
|
|
-{
|
|
|
- MigrationState *s;
|
|
|
-
|
|
|
- s = migrate_get_current();
|
|
|
-
|
|
|
- return s->parameters.decompress_threads;
|
|
|
-}
|
|
|
-
|
|
|
-bool migrate_dirty_bitmaps(void)
|
|
|
-{
|
|
|
- MigrationState *s;
|
|
|
-
|
|
|
- s = migrate_get_current();
|
|
|
-
|
|
|
- return s->capabilities[MIGRATION_CAPABILITY_DIRTY_BITMAPS];
|
|
|
-}
|
|
|
-
|
|
|
-bool migrate_ignore_shared(void)
|
|
|
-{
|
|
|
- MigrationState *s;
|
|
|
-
|
|
|
- s = migrate_get_current();
|
|
|
-
|
|
|
- return s->capabilities[MIGRATION_CAPABILITY_X_IGNORE_SHARED];
|
|
|
-}
|
|
|
-
|
|
|
-bool migrate_validate_uuid(void)
|
|
|
-{
|
|
|
- MigrationState *s;
|
|
|
-
|
|
|
- s = migrate_get_current();
|
|
|
-
|
|
|
- return s->capabilities[MIGRATION_CAPABILITY_VALIDATE_UUID];
|
|
|
-}
|
|
|
-
|
|
|
-bool migrate_use_events(void)
|
|
|
-{
|
|
|
- MigrationState *s;
|
|
|
-
|
|
|
- s = migrate_get_current();
|
|
|
-
|
|
|
- return s->capabilities[MIGRATION_CAPABILITY_EVENTS];
|
|
|
-}
|
|
|
-
|
|
|
-bool migrate_use_multifd(void)
|
|
|
-{
|
|
|
- MigrationState *s;
|
|
|
-
|
|
|
- s = migrate_get_current();
|
|
|
-
|
|
|
- return s->capabilities[MIGRATION_CAPABILITY_MULTIFD];
|
|
|
-}
|
|
|
-
|
|
|
-bool migrate_pause_before_switchover(void)
|
|
|
-{
|
|
|
- MigrationState *s;
|
|
|
-
|
|
|
- s = migrate_get_current();
|
|
|
-
|
|
|
- return s->capabilities[MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER];
|
|
|
-}
|
|
|
-
|
|
|
-int migrate_multifd_channels(void)
|
|
|
-{
|
|
|
- MigrationState *s;
|
|
|
-
|
|
|
- s = migrate_get_current();
|
|
|
-
|
|
|
- return s->parameters.multifd_channels;
|
|
|
-}
|
|
|
-
|
|
|
-MultiFDCompression migrate_multifd_compression(void)
|
|
|
-{
|
|
|
- MigrationState *s;
|
|
|
-
|
|
|
- s = migrate_get_current();
|
|
|
-
|
|
|
- assert(s->parameters.multifd_compression < MULTIFD_COMPRESSION__MAX);
|
|
|
- return s->parameters.multifd_compression;
|
|
|
-}
|
|
|
-
|
|
|
-int migrate_multifd_zlib_level(void)
|
|
|
-{
|
|
|
- MigrationState *s;
|
|
|
-
|
|
|
- s = migrate_get_current();
|
|
|
-
|
|
|
- return s->parameters.multifd_zlib_level;
|
|
|
-}
|
|
|
-
|
|
|
-int migrate_multifd_zstd_level(void)
|
|
|
-{
|
|
|
- MigrationState *s;
|
|
|
-
|
|
|
- s = migrate_get_current();
|
|
|
-
|
|
|
- return s->parameters.multifd_zstd_level;
|
|
|
-}
|
|
|
-
|
|
|
-#ifdef CONFIG_LINUX
|
|
|
-bool migrate_use_zero_copy_send(void)
|
|
|
-{
|
|
|
- MigrationState *s;
|
|
|
-
|
|
|
- s = migrate_get_current();
|
|
|
-
|
|
|
- return s->capabilities[MIGRATION_CAPABILITY_ZERO_COPY_SEND];
|
|
|
-}
|
|
|
-#endif
|
|
|
-
|
|
|
int migrate_use_tls(void)
|
|
|
{
|
|
|
MigrationState *s;
|
|
@@ -2763,78 +2186,6 @@ int migrate_use_tls(void)
|
|
|
return s->parameters.tls_creds && *s->parameters.tls_creds;
|
|
|
}
|
|
|
|
|
|
-int migrate_use_xbzrle(void)
|
|
|
-{
|
|
|
- MigrationState *s;
|
|
|
-
|
|
|
- s = migrate_get_current();
|
|
|
-
|
|
|
- return s->capabilities[MIGRATION_CAPABILITY_XBZRLE];
|
|
|
-}
|
|
|
-
|
|
|
-uint64_t migrate_xbzrle_cache_size(void)
|
|
|
-{
|
|
|
- MigrationState *s;
|
|
|
-
|
|
|
- s = migrate_get_current();
|
|
|
-
|
|
|
- return s->parameters.xbzrle_cache_size;
|
|
|
-}
|
|
|
-
|
|
|
-static int64_t migrate_max_postcopy_bandwidth(void)
|
|
|
-{
|
|
|
- MigrationState *s;
|
|
|
-
|
|
|
- s = migrate_get_current();
|
|
|
-
|
|
|
- return s->parameters.max_postcopy_bandwidth;
|
|
|
-}
|
|
|
-
|
|
|
-bool migrate_use_block(void)
|
|
|
-{
|
|
|
- MigrationState *s;
|
|
|
-
|
|
|
- s = migrate_get_current();
|
|
|
-
|
|
|
- return s->capabilities[MIGRATION_CAPABILITY_BLOCK];
|
|
|
-}
|
|
|
-
|
|
|
-bool migrate_use_return_path(void)
|
|
|
-{
|
|
|
- MigrationState *s;
|
|
|
-
|
|
|
- s = migrate_get_current();
|
|
|
-
|
|
|
- return s->capabilities[MIGRATION_CAPABILITY_RETURN_PATH];
|
|
|
-}
|
|
|
-
|
|
|
-bool migrate_use_block_incremental(void)
|
|
|
-{
|
|
|
- MigrationState *s;
|
|
|
-
|
|
|
- s = migrate_get_current();
|
|
|
-
|
|
|
- return s->parameters.block_incremental;
|
|
|
-}
|
|
|
-
|
|
|
-bool migrate_background_snapshot(void)
|
|
|
-{
|
|
|
- MigrationState *s;
|
|
|
-
|
|
|
- s = migrate_get_current();
|
|
|
-
|
|
|
- return s->capabilities[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT];
|
|
|
-}
|
|
|
-
|
|
|
-bool migrate_postcopy_preempt(void)
|
|
|
-{
|
|
|
- MigrationState *s;
|
|
|
-
|
|
|
- s = migrate_get_current();
|
|
|
-
|
|
|
- return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT];
|
|
|
-}
|
|
|
-
|
|
|
/* migration thread support */
|
|
|
/*
|
|
|
* Something bad happened to the RP stream, mark an error
|
|
@@ -3431,7 +2782,6 @@ static void migration_completion(MigrationState *s)
|
|
|
ret = global_state_store();
|
|
|
|
|
|
if (!ret) {
|
|
|
- bool inactivate = !migrate_colo_enabled();
|
|
|
ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
|
|
|
trace_migration_completion_vm_stop(ret);
|
|
|
if (ret >= 0) {
|
|
@@ -3439,10 +2789,10 @@ static void migration_completion(MigrationState *s)
|
|
|
MIGRATION_STATUS_DEVICE);
|
|
|
}
|
|
|
if (ret >= 0) {
|
|
|
- s->block_inactive = inactivate;
|
|
|
+ s->block_inactive = !migrate_colo();
|
|
|
qemu_file_set_rate_limit(s->to_dst_file, INT64_MAX);
|
|
|
ret = qemu_savevm_state_complete_precopy(s->to_dst_file, false,
|
|
|
- inactivate);
|
|
|
+ s->block_inactive);
|
|
|
}
|
|
|
}
|
|
|
qemu_mutex_unlock_iothread();
|
|
@@ -3492,7 +2842,7 @@ static void migration_completion(MigrationState *s)
|
|
|
goto fail_invalidate;
|
|
|
}
|
|
|
|
|
|
- if (migrate_colo_enabled() && s->state == MIGRATION_STATUS_ACTIVE) {
|
|
|
+ if (migrate_colo() && s->state == MIGRATION_STATUS_ACTIVE) {
|
|
|
/* COLO does not support postcopy */
|
|
|
migrate_set_state(&s->state, MIGRATION_STATUS_ACTIVE,
|
|
|
MIGRATION_STATUS_COLO);
|
|
@@ -3571,12 +2921,6 @@ fail:
|
|
|
MIGRATION_STATUS_FAILED);
|
|
|
}
|
|
|
|
|
|
-bool migrate_colo_enabled(void)
|
|
|
-{
|
|
|
- MigrationState *s = migrate_get_current();
|
|
|
- return s->capabilities[MIGRATION_CAPABILITY_X_COLO];
|
|
|
-}
|
|
|
-
|
|
|
typedef enum MigThrError {
|
|
|
/* No error detected */
|
|
|
MIG_THR_ERR_NONE = 0,
|
|
@@ -3907,7 +3251,7 @@ static void migration_iteration_finish(MigrationState *s)
|
|
|
runstate_set(RUN_STATE_POSTMIGRATE);
|
|
|
break;
|
|
|
case MIGRATION_STATUS_COLO:
|
|
|
- if (!migrate_colo_enabled()) {
|
|
|
+ if (!migrate_colo()) {
|
|
|
error_report("%s: critical error: calling COLO code without "
|
|
|
"COLO enabled", __func__);
|
|
|
}
|
|
@@ -4103,7 +3447,7 @@ static void *migration_thread(void *opaque)
|
|
|
qemu_savevm_send_postcopy_advise(s->to_dst_file);
|
|
|
}
|
|
|
|
|
|
- if (migrate_colo_enabled()) {
|
|
|
+ if (migrate_colo()) {
|
|
|
/* Notify migration destination that we enable COLO */
|
|
|
qemu_savevm_send_colo_enable(s->to_dst_file);
|
|
|
}
|
|
@@ -4355,11 +3699,11 @@ void migrate_fd_connect(MigrationState *s, Error *error_in)
|
|
|
|
|
|
if (resume) {
|
|
|
/* This is a resumed migration */
|
|
|
- rate_limit = s->parameters.max_postcopy_bandwidth /
|
|
|
+ rate_limit = migrate_max_postcopy_bandwidth() /
|
|
|
XFER_LIMIT_RATIO;
|
|
|
} else {
|
|
|
/* This is a fresh new migration */
|
|
|
- rate_limit = s->parameters.max_bandwidth / XFER_LIMIT_RATIO;
|
|
|
+ rate_limit = migrate_max_bandwidth() / XFER_LIMIT_RATIO;
|
|
|
|
|
|
/* Notify before starting migration thread */
|
|
|
notifier_list_notify(&migration_state_notifiers, s);
|
|
@@ -4373,7 +3717,7 @@ void migrate_fd_connect(MigrationState *s, Error *error_in)
|
|
|
* precopy, only if user specified "return-path" capability would
|
|
|
* QEMU uses the return path.
|
|
|
*/
|
|
|
- if (migrate_postcopy_ram() || migrate_use_return_path()) {
|
|
|
+ if (migrate_postcopy_ram() || migrate_return_path()) {
|
|
|
if (open_return_path_on_source(s, !resume)) {
|
|
|
error_report("Unable to open return-path for postcopy");
|
|
|
migrate_set_state(&s->state, s->state, MIGRATION_STATUS_FAILED);
|
|
@@ -4417,25 +3761,6 @@ void migrate_fd_connect(MigrationState *s, Error *error_in)
|
|
|
s->migration_thread_running = true;
|
|
|
}
|
|
|
|
|
|
-void migration_global_dump(Monitor *mon)
|
|
|
-{
|
|
|
- MigrationState *ms = migrate_get_current();
|
|
|
-
|
|
|
- monitor_printf(mon, "globals:\n");
|
|
|
- monitor_printf(mon, "store-global-state: %s\n",
|
|
|
- ms->store_global_state ? "on" : "off");
|
|
|
- monitor_printf(mon, "only-migratable: %s\n",
|
|
|
- only_migratable ? "on" : "off");
|
|
|
- monitor_printf(mon, "send-configuration: %s\n",
|
|
|
- ms->send_configuration ? "on" : "off");
|
|
|
- monitor_printf(mon, "send-section-footer: %s\n",
|
|
|
- ms->send_section_footer ? "on" : "off");
|
|
|
- monitor_printf(mon, "decompress-error-check: %s\n",
|
|
|
- ms->decompress_error_check ? "on" : "off");
|
|
|
- monitor_printf(mon, "clear-bitmap-shift: %u\n",
|
|
|
- ms->clear_bitmap_shift);
|
|
|
-}
|
|
|
-
|
|
|
#define DEFINE_PROP_MIG_CAP(name, x) \
|
|
|
DEFINE_PROP_BOOL(name, MigrationState, capabilities[x], false)
|
|
|
|