aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/virtio/virtio-balloon.c1
-rw-r--r--include/migration/misc.h1
-rw-r--r--migration/block-dirty-bitmap.c1
-rw-r--r--migration/block.c5
-rw-r--r--migration/colo.c6
-rw-r--r--migration/meson.build1
-rw-r--r--migration/migration-hmp-cmds.c39
-rw-r--r--migration/migration.c719
-rw-r--r--migration/migration.h40
-rw-r--r--migration/multifd-zlib.c1
-rw-r--r--migration/multifd-zstd.c1
-rw-r--r--migration/multifd.c24
-rw-r--r--migration/options.c722
-rw-r--r--migration/options.h76
-rw-r--r--migration/postcopy-ram.c1
-rw-r--r--migration/ram.c43
-rw-r--r--migration/rdma.c12
-rw-r--r--migration/savevm.c3
-rw-r--r--migration/socket.c5
-rw-r--r--qapi/migration.json28
-rw-r--r--qapi/ui.json28
-rw-r--r--ui/ui-hmp-cmds.c17
-rw-r--r--ui/ui-qmp-cmds.c29
23 files changed, 971 insertions, 832 deletions
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index 746f07c..43092aa 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -32,6 +32,7 @@
#include "qemu/error-report.h"
#include "migration/misc.h"
#include "migration/migration.h"
+#include "migration/options.h"
#include "hw/virtio/virtio-bus.h"
#include "hw/virtio/virtio-access.h"
diff --git a/include/migration/misc.h b/include/migration/misc.h
index 8b49841..5ebe13b 100644
--- a/include/migration/misc.h
+++ b/include/migration/misc.h
@@ -66,7 +66,6 @@ bool migration_has_finished(MigrationState *);
bool migration_has_failed(MigrationState *);
/* ...and after the device transmission */
bool migration_in_postcopy_after_devices(MigrationState *);
-void migration_global_dump(Monitor *mon);
/* True if incoming migration entered POSTCOPY_INCOMING_DISCARD */
bool migration_in_incoming_postcopy(void);
/* True if incoming migration entered POSTCOPY_INCOMING_ADVISE */
diff --git a/migration/block-dirty-bitmap.c b/migration/block-dirty-bitmap.c
index fe73aa9..a6ffae0 100644
--- a/migration/block-dirty-bitmap.c
+++ b/migration/block-dirty-bitmap.c
@@ -79,6 +79,7 @@
#include "qapi/qapi-visit-migration.h"
#include "qapi/clone-visitor.h"
#include "trace.h"
+#include "options.h"
#define CHUNK_SIZE (1 << 10)
diff --git a/migration/block.c b/migration/block.c
index b2497bb..6d532ac 100644
--- a/migration/block.c
+++ b/migration/block.c
@@ -28,6 +28,7 @@
#include "migration/vmstate.h"
#include "sysemu/block-backend.h"
#include "trace.h"
+#include "options.h"
#define BLK_MIG_BLOCK_SIZE (1ULL << 20)
#define BDRV_SECTORS_PER_DIRTY_CHUNK (BLK_MIG_BLOCK_SIZE >> BDRV_SECTOR_BITS)
@@ -416,7 +417,7 @@ static int init_blk_migration(QEMUFile *f)
bmds->bulk_completed = 0;
bmds->total_sectors = sectors;
bmds->completed_sectors = 0;
- bmds->shared_base = migrate_use_block_incremental();
+ bmds->shared_base = migrate_block_incremental();
assert(i < num_bs);
bmds_bs[i].bmds = bmds;
@@ -1000,7 +1001,7 @@ static int block_load(QEMUFile *f, void *opaque, int version_id)
static bool block_is_active(void *opaque)
{
- return migrate_use_block();
+ return migrate_block();
}
static SaveVMHandlers savevm_block_handlers = {
diff --git a/migration/colo.c b/migration/colo.c
index 0716e64..07bfa21 100644
--- a/migration/colo.c
+++ b/migration/colo.c
@@ -36,6 +36,7 @@
#include "sysemu/cpus.h"
#include "sysemu/runstate.h"
#include "net/filter.h"
+#include "options.h"
static bool vmstate_loading;
static Notifier packets_compare_notifier;
@@ -575,7 +576,7 @@ static void colo_process_checkpoint(MigrationState *s)
trace_colo_vm_state_change("stop", "run");
timer_mod(s->colo_delay_timer, qemu_clock_get_ms(QEMU_CLOCK_HOST) +
- s->parameters.x_checkpoint_delay);
+ migrate_checkpoint_delay());
while (s->state == MIGRATION_STATUS_COLO) {
if (failover_get_state() != FAILOVER_STATUS_NONE) {
@@ -650,8 +651,7 @@ void colo_checkpoint_notify(void *opaque)
qemu_event_set(&s->colo_checkpoint_event);
s->colo_checkpoint_time = qemu_clock_get_ms(QEMU_CLOCK_HOST);
- next_notify_time = s->colo_checkpoint_time +
- s->parameters.x_checkpoint_delay;
+ next_notify_time = s->colo_checkpoint_time + migrate_checkpoint_delay();
timer_mod(s->colo_delay_timer, next_notify_time);
}
diff --git a/migration/meson.build b/migration/meson.build
index 0d1bb9f..480ff68 100644
--- a/migration/meson.build
+++ b/migration/meson.build
@@ -22,6 +22,7 @@ softmmu_ss.add(files(
'migration.c',
'multifd.c',
'multifd-zlib.c',
+ 'options.c',
'postcopy-ram.c',
'savevm.c',
'socket.c',
diff --git a/migration/migration-hmp-cmds.c b/migration/migration-hmp-cmds.c
index 72519ea..4e9f00e 100644
--- a/migration/migration-hmp-cmds.c
+++ b/migration/migration-hmp-cmds.c
@@ -15,7 +15,6 @@
#include "qemu/osdep.h"
#include "block/qapi.h"
-#include "migration/misc.h"
#include "migration/snapshot.h"
#include "monitor/hmp.h"
#include "monitor/monitor.h"
@@ -30,6 +29,27 @@
#include "qemu/sockets.h"
#include "sysemu/runstate.h"
#include "ui/qemu-spice.h"
+#include "sysemu/sysemu.h"
+#include "migration.h"
+
+static 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);
+}
void hmp_info_migrate(Monitor *mon, const QDict *qdict)
{
@@ -616,23 +636,6 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
hmp_handle_error(mon, err);
}
-void hmp_client_migrate_info(Monitor *mon, const QDict *qdict)
-{
- Error *err = NULL;
- const char *protocol = qdict_get_str(qdict, "protocol");
- const char *hostname = qdict_get_str(qdict, "hostname");
- bool has_port = qdict_haskey(qdict, "port");
- int port = qdict_get_try_int(qdict, "port", -1);
- bool has_tls_port = qdict_haskey(qdict, "tls-port");
- int tls_port = qdict_get_try_int(qdict, "tls-port", -1);
- const char *cert_subject = qdict_get_try_str(qdict, "cert-subject");
-
- qmp_client_migrate_info(protocol, hostname,
- has_port, port, has_tls_port, tls_port,
- cert_subject, &err);
- hmp_handle_error(mon, err);
-}
-
void hmp_migrate_start_postcopy(Monitor *mon, const QDict *qdict)
{
Error *err = NULL;
diff --git a/migration/migration.c b/migration/migration.c
index d91fe9f..53dd59f 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -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 &ap;
-}
-
/*
* 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)
diff --git a/migration/migration.h b/migration/migration.h
index 04e0860..dcf9068 100644
--- a/migration/migration.h
+++ b/migration/migration.h
@@ -447,50 +447,10 @@ bool migration_is_blocked(Error **errp);
bool migration_in_postcopy(void);
MigrationState *migrate_get_current(void);
-bool migrate_postcopy(void);
-
-bool migrate_release_ram(void);
-bool migrate_postcopy_ram(void);
-bool migrate_zero_blocks(void);
-bool migrate_dirty_bitmaps(void);
-bool migrate_ignore_shared(void);
-bool migrate_validate_uuid(void);
-
-bool migrate_auto_converge(void);
-bool migrate_use_multifd(void);
-bool migrate_pause_before_switchover(void);
-int migrate_multifd_channels(void);
-MultiFDCompression migrate_multifd_compression(void);
-int migrate_multifd_zlib_level(void);
-int migrate_multifd_zstd_level(void);
-
-#ifdef CONFIG_LINUX
-bool migrate_use_zero_copy_send(void);
-#else
-#define migrate_use_zero_copy_send() (false)
-#endif
int migrate_use_tls(void);
-int migrate_use_xbzrle(void);
-uint64_t migrate_xbzrle_cache_size(void);
-bool migrate_colo_enabled(void);
-
-bool migrate_use_block(void);
-bool migrate_use_block_incremental(void);
-int migrate_max_cpu_throttle(void);
-bool migrate_use_return_path(void);
uint64_t ram_get_total_transferred_pages(void);
-bool migrate_use_compression(void);
-int migrate_compress_level(void);
-int migrate_compress_threads(void);
-int migrate_compress_wait_thread(void);
-int migrate_decompress_threads(void);
-bool migrate_use_events(void);
-bool migrate_postcopy_blocktime(void);
-bool migrate_background_snapshot(void);
-bool migrate_postcopy_preempt(void);
-
/* Sending on the return path - generic and then for each message type */
void migrate_send_rp_shut(MigrationIncomingState *mis,
uint32_t value);
diff --git a/migration/multifd-zlib.c b/migration/multifd-zlib.c
index 3777024..8170125 100644
--- a/migration/multifd-zlib.c
+++ b/migration/multifd-zlib.c
@@ -18,6 +18,7 @@
#include "qapi/error.h"
#include "migration.h"
#include "trace.h"
+#include "options.h"
#include "multifd.h"
struct zlib_data {
diff --git a/migration/multifd-zstd.c b/migration/multifd-zstd.c
index f4a8e1e..d1d29e7 100644
--- a/migration/multifd-zstd.c
+++ b/migration/multifd-zstd.c
@@ -18,6 +18,7 @@
#include "qapi/error.h"
#include "migration.h"
#include "trace.h"
+#include "options.h"
#include "multifd.h"
struct zstd_data {
diff --git a/migration/multifd.c b/migration/multifd.c
index 903df21..cce3ad6 100644
--- a/migration/multifd.c
+++ b/migration/multifd.c
@@ -25,7 +25,7 @@
#include "trace.h"
#include "multifd.h"
#include "threadinfo.h"
-
+#include "options.h"
#include "qemu/yank.h"
#include "io/channel-socket.h"
#include "yank_functions.h"
@@ -516,7 +516,7 @@ void multifd_save_cleanup(void)
{
int i;
- if (!migrate_use_multifd()) {
+ if (!migrate_multifd()) {
return;
}
multifd_send_terminate_threads(NULL);
@@ -587,7 +587,7 @@ int multifd_send_sync_main(QEMUFile *f)
int i;
bool flush_zero_copy;
- if (!migrate_use_multifd()) {
+ if (!migrate_multifd()) {
return 0;
}
if (multifd_send_state->pages->num) {
@@ -608,7 +608,7 @@ int multifd_send_sync_main(QEMUFile *f)
* all the dirty bitmaps.
*/
- flush_zero_copy = migrate_use_zero_copy_send();
+ flush_zero_copy = migrate_zero_copy_send();
for (i = 0; i < migrate_multifd_channels(); i++) {
MultiFDSendParams *p = &multifd_send_state->params[i];
@@ -653,7 +653,7 @@ static void *multifd_send_thread(void *opaque)
MigrationThread *thread = NULL;
Error *local_err = NULL;
int ret = 0;
- bool use_zero_copy_send = migrate_use_zero_copy_send();
+ bool use_zero_copy_send = migrate_zero_copy_send();
thread = MigrationThreadAdd(p->name, qemu_get_thread_id());
@@ -911,7 +911,7 @@ int multifd_save_setup(Error **errp)
uint32_t page_count = MULTIFD_PACKET_SIZE / qemu_target_page_size();
uint8_t i;
- if (!migrate_use_multifd()) {
+ if (!migrate_multifd()) {
return 0;
}
@@ -945,7 +945,7 @@ int multifd_save_setup(Error **errp)
p->page_size = qemu_target_page_size();
p->page_count = page_count;
- if (migrate_use_zero_copy_send()) {
+ if (migrate_zero_copy_send()) {
p->write_flags = QIO_CHANNEL_WRITE_FLAG_ZERO_COPY;
} else {
p->write_flags = 0;
@@ -1016,7 +1016,7 @@ static void multifd_recv_terminate_threads(Error *err)
void multifd_load_shutdown(void)
{
- if (migrate_use_multifd()) {
+ if (migrate_multifd()) {
multifd_recv_terminate_threads(NULL);
}
}
@@ -1025,7 +1025,7 @@ void multifd_load_cleanup(void)
{
int i;
- if (!migrate_use_multifd()) {
+ if (!migrate_multifd()) {
return;
}
multifd_recv_terminate_threads(NULL);
@@ -1072,7 +1072,7 @@ void multifd_recv_sync_main(void)
{
int i;
- if (!migrate_use_multifd()) {
+ if (!migrate_multifd()) {
return;
}
for (i = 0; i < migrate_multifd_channels(); i++) {
@@ -1170,7 +1170,7 @@ int multifd_load_setup(Error **errp)
* Return successfully if multiFD recv state is already initialised
* or multiFD is not enabled.
*/
- if (multifd_recv_state || !migrate_use_multifd()) {
+ if (multifd_recv_state || !migrate_multifd()) {
return 0;
}
@@ -1216,7 +1216,7 @@ bool multifd_recv_all_channels_created(void)
{
int thread_count = migrate_multifd_channels();
- if (!migrate_use_multifd()) {
+ if (!migrate_multifd()) {
return true;
}
diff --git a/migration/options.c b/migration/options.c
new file mode 100644
index 0000000..8e8753d
--- /dev/null
+++ b/migration/options.c
@@ -0,0 +1,722 @@
+/*
+ * QEMU migration capabilities
+ *
+ * Copyright (c) 2012-2023 Red Hat Inc
+ *
+ * Authors:
+ * Orit Wasserman <owasserm@redhat.com>
+ * Juan Quintela <quintela@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/clone-visitor.h"
+#include "qapi/error.h"
+#include "qapi/qapi-commands-migration.h"
+#include "qapi/qapi-visit-migration.h"
+#include "qapi/qmp/qerror.h"
+#include "sysemu/runstate.h"
+#include "migration/misc.h"
+#include "migration.h"
+#include "ram.h"
+#include "options.h"
+
+bool migrate_auto_converge(void)
+{
+ MigrationState *s;
+
+ s = migrate_get_current();
+
+ return s->capabilities[MIGRATION_CAPABILITY_AUTO_CONVERGE];
+}
+
+bool migrate_background_snapshot(void)
+{
+ MigrationState *s;
+
+ s = migrate_get_current();
+
+ return s->capabilities[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT];
+}
+
+bool migrate_block(void)
+{
+ MigrationState *s;
+
+ s = migrate_get_current();
+
+ return s->capabilities[MIGRATION_CAPABILITY_BLOCK];
+}
+
+bool migrate_colo(void)
+{
+ MigrationState *s = migrate_get_current();
+ return s->capabilities[MIGRATION_CAPABILITY_X_COLO];
+}
+
+bool migrate_compress(void)
+{
+ MigrationState *s;
+
+ s = migrate_get_current();
+
+ return s->capabilities[MIGRATION_CAPABILITY_COMPRESS];
+}
+
+bool migrate_dirty_bitmaps(void)
+{
+ MigrationState *s;
+
+ s = migrate_get_current();
+
+ return s->capabilities[MIGRATION_CAPABILITY_DIRTY_BITMAPS];
+}
+
+bool migrate_events(void)
+{
+ MigrationState *s;
+
+ s = migrate_get_current();
+
+ return s->capabilities[MIGRATION_CAPABILITY_EVENTS];
+}
+
+bool migrate_ignore_shared(void)
+{
+ MigrationState *s;
+
+ s = migrate_get_current();
+
+ return s->capabilities[MIGRATION_CAPABILITY_X_IGNORE_SHARED];
+}
+
+bool migrate_late_block_activate(void)
+{
+ MigrationState *s;
+
+ s = migrate_get_current();
+
+ return s->capabilities[MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE];
+}
+
+bool migrate_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];
+}
+
+bool migrate_postcopy_blocktime(void)
+{
+ MigrationState *s;
+
+ s = migrate_get_current();
+
+ return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME];
+}
+
+bool migrate_postcopy_preempt(void)
+{
+ MigrationState *s;
+
+ s = migrate_get_current();
+
+ return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT];
+}
+
+bool migrate_postcopy_ram(void)
+{
+ MigrationState *s;
+
+ s = migrate_get_current();
+
+ return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_RAM];
+}
+
+bool migrate_rdma_pin_all(void)
+{
+ MigrationState *s = migrate_get_current();
+
+ return s->capabilities[MIGRATION_CAPABILITY_RDMA_PIN_ALL];
+}
+
+bool migrate_release_ram(void)
+{
+ MigrationState *s;
+
+ s = migrate_get_current();
+
+ return s->capabilities[MIGRATION_CAPABILITY_RELEASE_RAM];
+}
+
+bool migrate_return_path(void)
+{
+ MigrationState *s;
+
+ s = migrate_get_current();
+
+ return s->capabilities[MIGRATION_CAPABILITY_RETURN_PATH];
+}
+
+bool migrate_validate_uuid(void)
+{
+ MigrationState *s;
+
+ s = migrate_get_current();
+
+ return s->capabilities[MIGRATION_CAPABILITY_VALIDATE_UUID];
+}
+
+bool migrate_xbzrle(void)
+{
+ MigrationState *s;
+
+ s = migrate_get_current();
+
+ return s->capabilities[MIGRATION_CAPABILITY_XBZRLE];
+}
+
+bool migrate_zero_blocks(void)
+{
+ MigrationState *s;
+
+ s = migrate_get_current();
+
+ return s->capabilities[MIGRATION_CAPABILITY_ZERO_BLOCKS];
+}
+
+bool migrate_zero_copy_send(void)
+{
+ MigrationState *s;
+
+ s = migrate_get_current();
+
+ return s->capabilities[MIGRATION_CAPABILITY_ZERO_COPY_SEND];
+}
+
+/* pseudo capabilities */
+
+bool migrate_postcopy(void)
+{
+ return migrate_postcopy_ram() || migrate_dirty_bitmaps();
+}
+
+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 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);
+
+/**
+ * @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.
+ */
+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;
+}
+
+bool migrate_cap_set(int cap, bool value, Error **errp)
+{
+ MigrationState *s = migrate_get_current();
+ bool new_caps[MIGRATION_CAPABILITY__MAX];
+
+ if (migration_is_running(s->state)) {
+ error_setg(errp, QERR_MIGRATION_ACTIVE);
+ return false;
+ }
+
+ memcpy(new_caps, s->capabilities, sizeof(new_caps));
+ new_caps[cap] = value;
+
+ if (!migrate_caps_check(s->capabilities, new_caps, errp)) {
+ return false;
+ }
+ s->capabilities[cap] = value;
+ return true;
+}
+
+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;
+}
+
+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;
+ }
+}
+
+/* parameters */
+
+bool migrate_block_incremental(void)
+{
+ MigrationState *s;
+
+ s = migrate_get_current();
+
+ return s->parameters.block_incremental;
+}
+
+uint32_t migrate_checkpoint_delay(void)
+{
+ MigrationState *s;
+
+ s = migrate_get_current();
+
+ return s->parameters.x_checkpoint_delay;
+}
+
+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;
+}
+
+uint8_t migrate_cpu_throttle_increment(void)
+{
+ MigrationState *s;
+
+ s = migrate_get_current();
+
+ return s->parameters.cpu_throttle_increment;
+}
+
+uint8_t migrate_cpu_throttle_initial(void)
+{
+ MigrationState *s;
+
+ s = migrate_get_current();
+
+ return s->parameters.cpu_throttle_initial;
+}
+
+bool migrate_cpu_throttle_tailslow(void)
+{
+ MigrationState *s;
+
+ s = migrate_get_current();
+
+ return s->parameters.cpu_throttle_tailslow;
+}
+
+int migrate_decompress_threads(void)
+{
+ MigrationState *s;
+
+ s = migrate_get_current();
+
+ return s->parameters.decompress_threads;
+}
+
+uint8_t migrate_max_cpu_throttle(void)
+{
+ MigrationState *s;
+
+ s = migrate_get_current();
+
+ return s->parameters.max_cpu_throttle;
+}
+
+uint64_t migrate_max_bandwidth(void)
+{
+ MigrationState *s;
+
+ s = migrate_get_current();
+
+ return s->parameters.max_bandwidth;
+}
+
+int64_t migrate_max_postcopy_bandwidth(void)
+{
+ MigrationState *s;
+
+ s = migrate_get_current();
+
+ return s->parameters.max_postcopy_bandwidth;
+}
+
+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;
+}
+
+uint8_t migrate_throttle_trigger_threshold(void)
+{
+ MigrationState *s;
+
+ s = migrate_get_current();
+
+ return s->parameters.throttle_trigger_threshold;
+}
+
+uint64_t migrate_xbzrle_cache_size(void)
+{
+ MigrationState *s;
+
+ s = migrate_get_current();
+
+ return s->parameters.xbzrle_cache_size;
+}
+
+/* parameters helpers */
+
+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 &ap;
+}
+
+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;
+}
diff --git a/migration/options.h b/migration/options.h
new file mode 100644
index 0000000..1b78fa9
--- /dev/null
+++ b/migration/options.h
@@ -0,0 +1,76 @@
+/*
+ * QEMU migration capabilities
+ *
+ * Copyright (c) 2012-2023 Red Hat Inc
+ *
+ * Authors:
+ * Orit Wasserman <owasserm@redhat.com>
+ * Juan Quintela <quintela@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef QEMU_MIGRATION_OPTIONS_H
+#define QEMU_MIGRATION_OPTIONS_H
+
+/* capabilities */
+
+bool migrate_auto_converge(void);
+bool migrate_background_snapshot(void);
+bool migrate_block(void);
+bool migrate_colo(void);
+bool migrate_compress(void);
+bool migrate_dirty_bitmaps(void);
+bool migrate_events(void);
+bool migrate_ignore_shared(void);
+bool migrate_late_block_activate(void);
+bool migrate_multifd(void);
+bool migrate_pause_before_switchover(void);
+bool migrate_postcopy_blocktime(void);
+bool migrate_postcopy_preempt(void);
+bool migrate_postcopy_ram(void);
+bool migrate_rdma_pin_all(void);
+bool migrate_release_ram(void);
+bool migrate_return_path(void);
+bool migrate_validate_uuid(void);
+bool migrate_xbzrle(void);
+bool migrate_zero_blocks(void);
+bool migrate_zero_copy_send(void);
+
+/*
+ * pseudo capabilities
+ *
+ * These are functions that are used in a similar way to capabilities
+ * check, but they are not a capability.
+ */
+
+bool migrate_postcopy(void);
+
+/* capabilities helpers */
+
+bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp);
+bool migrate_cap_set(int cap, bool value, Error **errp);
+
+/* parameters */
+
+bool migrate_block_incremental(void);
+uint32_t migrate_checkpoint_delay(void);
+int migrate_compress_level(void);
+int migrate_compress_threads(void);
+int migrate_compress_wait_thread(void);
+uint8_t migrate_cpu_throttle_increment(void);
+uint8_t migrate_cpu_throttle_initial(void);
+bool migrate_cpu_throttle_tailslow(void);
+int migrate_decompress_threads(void);
+uint8_t migrate_max_cpu_throttle(void);
+uint64_t migrate_max_bandwidth(void);
+int64_t migrate_max_postcopy_bandwidth(void);
+int migrate_multifd_channels(void);
+MultiFDCompression migrate_multifd_compression(void);
+int migrate_multifd_zlib_level(void);
+int migrate_multifd_zstd_level(void);
+uint8_t migrate_throttle_trigger_threshold(void);
+uint64_t migrate_xbzrle_cache_size(void);
+
+#endif
diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c
index d7b48dd..0711500 100644
--- a/migration/postcopy-ram.c
+++ b/migration/postcopy-ram.c
@@ -37,6 +37,7 @@
#include "tls.h"
#include "qemu/userfaultfd.h"
#include "qemu/mmap-alloc.h"
+#include "options.h"
/* Arbitrary limit on size of each discard command,
* keeps them around ~200 bytes
diff --git a/migration/ram.c b/migration/ram.c
index 2297140..01356f6 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -57,6 +57,7 @@
#include "qemu/iov.h"
#include "multifd.h"
#include "sysemu/runstate.h"
+#include "options.h"
#include "hw/boards.h" /* for machine_dump_guest_core() */
@@ -155,14 +156,14 @@ static struct {
static void XBZRLE_cache_lock(void)
{
- if (migrate_use_xbzrle()) {
+ if (migrate_xbzrle()) {
qemu_mutex_lock(&XBZRLE.lock);
}
}
static void XBZRLE_cache_unlock(void)
{
- if (migrate_use_xbzrle()) {
+ if (migrate_xbzrle()) {
qemu_mutex_unlock(&XBZRLE.lock);
}
}
@@ -585,7 +586,7 @@ static void compress_threads_save_cleanup(void)
{
int i, thread_count;
- if (!migrate_use_compression() || !comp_param) {
+ if (!migrate_compress() || !comp_param) {
return;
}
@@ -624,7 +625,7 @@ static int compress_threads_save_setup(void)
{
int i, thread_count;
- if (!migrate_use_compression()) {
+ if (!migrate_compress()) {
return 0;
}
thread_count = migrate_compress_threads();
@@ -710,11 +711,10 @@ static size_t save_page_header(PageSearchStatus *pss, QEMUFile *f,
static void mig_throttle_guest_down(uint64_t bytes_dirty_period,
uint64_t bytes_dirty_threshold)
{
- MigrationState *s = migrate_get_current();
- uint64_t pct_initial = s->parameters.cpu_throttle_initial;
- uint64_t pct_increment = s->parameters.cpu_throttle_increment;
- bool pct_tailslow = s->parameters.cpu_throttle_tailslow;
- int pct_max = s->parameters.max_cpu_throttle;
+ uint64_t pct_initial = migrate_cpu_throttle_initial();
+ uint64_t pct_increment = migrate_cpu_throttle_increment();
+ bool pct_tailslow = migrate_cpu_throttle_tailslow();
+ int pct_max = migrate_max_cpu_throttle();
uint64_t throttle_now = cpu_throttle_get_percentage();
uint64_t cpu_now, cpu_ideal, throttle_inc;
@@ -1136,7 +1136,7 @@ static void migration_update_rates(RAMState *rs, int64_t end_time)
return;
}
- if (migrate_use_xbzrle()) {
+ if (migrate_xbzrle()) {
double encoded_size, unencoded_size;
xbzrle_counters.cache_miss_rate = (double)(xbzrle_counters.cache_miss -
@@ -1154,7 +1154,7 @@ static void migration_update_rates(RAMState *rs, int64_t end_time)
rs->xbzrle_bytes_prev = xbzrle_counters.bytes;
}
- if (migrate_use_compression()) {
+ if (migrate_compress()) {
compression_counters.busy_rate = (double)(compression_counters.busy -
rs->compress_thread_busy_prev) / page_count;
rs->compress_thread_busy_prev = compression_counters.busy;
@@ -1177,8 +1177,7 @@ static void migration_update_rates(RAMState *rs, int64_t end_time)
static void migration_trigger_throttle(RAMState *rs)
{
- MigrationState *s = migrate_get_current();
- uint64_t threshold = s->parameters.throttle_trigger_threshold;
+ uint64_t threshold = migrate_throttle_trigger_threshold();
uint64_t bytes_xfer_period =
stat64_get(&ram_counters.transferred) - rs->bytes_xfer_prev;
uint64_t bytes_dirty_period = rs->num_dirty_pages_period * TARGET_PAGE_SIZE;
@@ -1245,7 +1244,7 @@ static void migration_bitmap_sync(RAMState *rs)
rs->num_dirty_pages_period = 0;
rs->bytes_xfer_prev = stat64_get(&ram_counters.transferred);
}
- if (migrate_use_events()) {
+ if (migrate_events()) {
uint64_t generation = stat64_get(&ram_counters.dirty_sync_count);
qapi_event_send_migration_pass(generation);
}
@@ -1625,7 +1624,7 @@ static int find_dirty_block(RAMState *rs, PageSearchStatus *pss)
/* Flag that we've looped */
pss->complete_round = true;
/* After the first round, enable XBZRLE. */
- if (migrate_use_xbzrle()) {
+ if (migrate_xbzrle()) {
rs->xbzrle_enabled = true;
}
}
@@ -2269,7 +2268,7 @@ int ram_save_queue_pages(const char *rbname, ram_addr_t start, ram_addr_t len)
static bool save_page_use_compression(RAMState *rs)
{
- if (!migrate_use_compression()) {
+ if (!migrate_compress()) {
return false;
}
@@ -2361,7 +2360,7 @@ static int ram_save_target_page_legacy(RAMState *rs, PageSearchStatus *pss)
* if host page size == guest page size the dest guest during run may
* still see partially copied pages which is data corruption.
*/
- if (migrate_use_multifd() && !migration_in_postcopy()) {
+ if (migrate_multifd() && !migration_in_postcopy()) {
return ram_save_multifd_page(pss->pss_channel, block, offset);
}
@@ -2978,7 +2977,7 @@ static int xbzrle_init(void)
{
Error *local_err = NULL;
- if (!migrate_use_xbzrle()) {
+ if (!migrate_xbzrle()) {
return 0;
}
@@ -3733,7 +3732,7 @@ static int wait_for_decompress_done(void)
{
int idx, thread_count;
- if (!migrate_use_compression()) {
+ if (!migrate_compress()) {
return 0;
}
@@ -3752,7 +3751,7 @@ static void compress_threads_load_cleanup(void)
{
int i, thread_count;
- if (!migrate_use_compression()) {
+ if (!migrate_compress()) {
return;
}
thread_count = migrate_decompress_threads();
@@ -3793,7 +3792,7 @@ static int compress_threads_load_setup(QEMUFile *f)
{
int i, thread_count;
- if (!migrate_use_compression()) {
+ if (!migrate_compress()) {
return 0;
}
@@ -4259,7 +4258,7 @@ static int ram_load_precopy(QEMUFile *f)
int flags = 0, ret = 0, invalid_flags = 0, len = 0, i = 0;
/* ADVISE is earlier, it shows the source has the postcopy capability on */
bool postcopy_advised = migration_incoming_postcopy_advised();
- if (!migrate_use_compression()) {
+ if (!migrate_compress()) {
invalid_flags |= RAM_SAVE_FLAG_COMPRESS_PAGE;
}
diff --git a/migration/rdma.c b/migration/rdma.c
index f35f021..0af5e94 100644
--- a/migration/rdma.c
+++ b/migration/rdma.c
@@ -35,6 +35,7 @@
#include <rdma/rdma_cma.h>
#include "trace.h"
#include "qom/object.h"
+#include "options.h"
#include <poll.h>
/*
@@ -3373,7 +3374,7 @@ static int qemu_rdma_accept(RDMAContext *rdma)
* initialize the RDMAContext for return path for postcopy after first
* connection request reached.
*/
- if ((migrate_postcopy() || migrate_use_return_path())
+ if ((migrate_postcopy() || migrate_return_path())
&& !rdma->is_return_path) {
rdma_return_path = qemu_rdma_data_init(rdma->host_port, NULL);
if (rdma_return_path == NULL) {
@@ -3456,7 +3457,7 @@ static int qemu_rdma_accept(RDMAContext *rdma)
}
/* Accept the second connection request for return path */
- if ((migrate_postcopy() || migrate_use_return_path())
+ if ((migrate_postcopy() || migrate_return_path())
&& !rdma->is_return_path) {
qemu_set_fd_handler(rdma->channel->fd, rdma_accept_incoming_migration,
NULL,
@@ -4178,8 +4179,7 @@ void rdma_start_outgoing_migration(void *opaque,
goto err;
}
- ret = qemu_rdma_source_init(rdma,
- s->capabilities[MIGRATION_CAPABILITY_RDMA_PIN_ALL], errp);
+ ret = qemu_rdma_source_init(rdma, migrate_rdma_pin_all(), errp);
if (ret) {
goto err;
@@ -4193,7 +4193,7 @@ void rdma_start_outgoing_migration(void *opaque,
}
/* RDMA postcopy need a separate queue pair for return path */
- if (migrate_postcopy() || migrate_use_return_path()) {
+ if (migrate_postcopy() || migrate_return_path()) {
rdma_return_path = qemu_rdma_data_init(host_port, errp);
if (rdma_return_path == NULL) {
@@ -4201,7 +4201,7 @@ void rdma_start_outgoing_migration(void *opaque,
}
ret = qemu_rdma_source_init(rdma_return_path,
- s->capabilities[MIGRATION_CAPABILITY_RDMA_PIN_ALL], errp);
+ migrate_rdma_pin_all(), errp);
if (ret) {
goto return_path_err;
diff --git a/migration/savevm.c b/migration/savevm.c
index 589ef92..9671211 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -67,6 +67,7 @@
#include "qemu/yank.h"
#include "yank_functions.h"
#include "sysemu/qtest.h"
+#include "options.h"
const unsigned int postcopy_ram_discard_version;
@@ -1611,7 +1612,7 @@ static int qemu_savevm_state(QEMUFile *f, Error **errp)
return -EINVAL;
}
- if (migrate_use_block()) {
+ if (migrate_block()) {
error_setg(errp, "Block migration and snapshots are incompatible");
return -EINVAL;
}
diff --git a/migration/socket.c b/migration/socket.c
index e6fdf3c..1b6f5ba 100644
--- a/migration/socket.c
+++ b/migration/socket.c
@@ -27,6 +27,7 @@
#include "io/net-listener.h"
#include "trace.h"
#include "postcopy-ram.h"
+#include "options.h"
struct SocketOutgoingArgs {
SocketAddress *saddr;
@@ -97,7 +98,7 @@ static void socket_outgoing_migration(QIOTask *task,
trace_migration_socket_outgoing_connected(data->hostname);
- if (migrate_use_zero_copy_send() &&
+ if (migrate_zero_copy_send() &&
!qio_channel_has_feature(sioc, QIO_CHANNEL_FEATURE_WRITE_ZERO_COPY)) {
error_setg(&err, "Zero copy send feature not detected in host kernel");
}
@@ -182,7 +183,7 @@ socket_start_incoming_migration_internal(SocketAddress *saddr,
qio_net_listener_set_name(listener, "migration-socket-listener");
- if (migrate_use_multifd()) {
+ if (migrate_multifd()) {
num = migrate_multifd_channels();
} else if (migrate_postcopy_preempt()) {
num = RAM_CHANNEL_MAX;
diff --git a/qapi/migration.json b/qapi/migration.json
index c84fa10..2c35b7b 100644
--- a/qapi/migration.json
+++ b/qapi/migration.json
@@ -1204,34 +1204,6 @@
'returns': 'MigrationParameters' }
##
-# @client_migrate_info:
-#
-# Set migration information for remote display. This makes the server
-# ask the client to automatically reconnect using the new parameters
-# once migration finished successfully. Only implemented for SPICE.
-#
-# @protocol: must be "spice"
-# @hostname: migration target hostname
-# @port: spice tcp port for plaintext channels
-# @tls-port: spice tcp port for tls-secured channels
-# @cert-subject: server certificate subject
-#
-# Since: 0.14
-#
-# Example:
-#
-# -> { "execute": "client_migrate_info",
-# "arguments": { "protocol": "spice",
-# "hostname": "virt42.lab.kraxel.org",
-# "port": 1234 } }
-# <- { "return": {} }
-#
-##
-{ 'command': 'client_migrate_info',
- 'data': { 'protocol': 'str', 'hostname': 'str', '*port': 'int',
- '*tls-port': 'int', '*cert-subject': 'str' } }
-
-##
# @migrate-start-postcopy:
#
# Followup to a migration command to switch the migration to postcopy mode.
diff --git a/qapi/ui.json b/qapi/ui.json
index 9832234..7ddd27a 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -1554,3 +1554,31 @@
{ 'command': 'display-update',
'data': 'DisplayUpdateOptions',
'boxed' : true }
+
+##
+# @client_migrate_info:
+#
+# Set migration information for remote display. This makes the server
+# ask the client to automatically reconnect using the new parameters
+# once migration finished successfully. Only implemented for SPICE.
+#
+# @protocol: must be "spice"
+# @hostname: migration target hostname
+# @port: spice tcp port for plaintext channels
+# @tls-port: spice tcp port for tls-secured channels
+# @cert-subject: server certificate subject
+#
+# Since: 0.14
+#
+# Example:
+#
+# -> { "execute": "client_migrate_info",
+# "arguments": { "protocol": "spice",
+# "hostname": "virt42.lab.kraxel.org",
+# "port": 1234 } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'client_migrate_info',
+ 'data': { 'protocol': 'str', 'hostname': 'str', '*port': 'int',
+ '*tls-port': 'int', '*cert-subject': 'str' } }
diff --git a/ui/ui-hmp-cmds.c b/ui/ui-hmp-cmds.c
index 5c456ec..c671389 100644
--- a/ui/ui-hmp-cmds.c
+++ b/ui/ui-hmp-cmds.c
@@ -458,3 +458,20 @@ hmp_screendump(Monitor *mon, const QDict *qdict)
end:
hmp_handle_error(mon, err);
}
+
+void hmp_client_migrate_info(Monitor *mon, const QDict *qdict)
+{
+ Error *err = NULL;
+ const char *protocol = qdict_get_str(qdict, "protocol");
+ const char *hostname = qdict_get_str(qdict, "hostname");
+ bool has_port = qdict_haskey(qdict, "port");
+ int port = qdict_get_try_int(qdict, "port", -1);
+ bool has_tls_port = qdict_haskey(qdict, "tls-port");
+ int tls_port = qdict_get_try_int(qdict, "tls-port", -1);
+ const char *cert_subject = qdict_get_try_str(qdict, "cert-subject");
+
+ qmp_client_migrate_info(protocol, hostname,
+ has_port, port, has_tls_port, tls_port,
+ cert_subject, &err);
+ hmp_handle_error(mon, err);
+}
diff --git a/ui/ui-qmp-cmds.c b/ui/ui-qmp-cmds.c
index dbc4afc..a37a702 100644
--- a/ui/ui-qmp-cmds.c
+++ b/ui/ui-qmp-cmds.c
@@ -175,3 +175,32 @@ void qmp_display_update(DisplayUpdateOptions *arg, Error **errp)
abort();
}
}
+
+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'");
+}