@@ -255,9 +255,10 @@ static bool
migration_capabilities_and_transport_compatible(MigrationAddress *addr,
Error **errp)
{
+ MigrationState *s = migrate_get_current();
+
if (addr->transport == MIGRATION_ADDRESS_TYPE_RDMA) {
- return migrate_rdma_caps_check(migrate_get_current()->capabilities,
- errp);
+ return migrate_rdma_caps_check(&s->parameters, errp);
}
return true;
@@ -4079,22 +4080,7 @@ static void migration_instance_init(Object *obj)
*/
static bool migration_object_check(MigrationState *ms, Error **errp)
{
- /* Assuming all off */
- bool old_caps[MIGRATION_CAPABILITY__MAX] = { 0 };
-
- if (!migrate_params_check(&ms->parameters, errp)) {
- return false;
- }
-
- /*
- * FIXME: Temporarily while -global capabilties are still using
- * s->capabilities. Will be gone by the end of the series.
- */
- for (int i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
- migrate_capability_set_compat(&ms->parameters, i, ms->capabilities[i]);
- }
-
- return migrate_caps_check(old_caps, ms->capabilities, errp);
+ return migrate_params_check(&ms->parameters, errp);
}
static const TypeInfo migration_type = {
@@ -357,7 +357,7 @@ struct MigrationState {
/* Timestamp when VM is down (ms) to migrate the last stuff */
int64_t downtime_start;
int64_t downtime;
- bool capabilities[MIGRATION_CAPABILITY__MAX];
+ int64_t expected_downtime;
int64_t setup_time;
/*
@@ -88,9 +88,6 @@
#define DEFAULT_MIGRATE_ANNOUNCE_ROUNDS 5
#define DEFAULT_MIGRATE_ANNOUNCE_STEP 100
-#define DEFINE_PROP_MIG_CAP(name, x) \
- DEFINE_PROP_BOOL(name, MigrationState, capabilities[x], false)
-
const PropertyInfo qdev_prop_StrOrNull;
#define DEFINE_PROP_STR_OR_NULL(_name, _state, _field) \
DEFINE_PROP(_name, _state, _field, qdev_prop_StrOrNull, StrOrNull *, \
@@ -198,32 +195,42 @@ const Property migration_properties[] = {
parameters.x_rdma_chunk_size,
DEFAULT_MIGRATE_X_RDMA_CHUNK_SIZE),
- /* Migration capabilities */
- DEFINE_PROP_MIG_CAP("x-xbzrle", MIGRATION_CAPABILITY_XBZRLE),
- DEFINE_PROP_MIG_CAP("x-rdma-pin-all", MIGRATION_CAPABILITY_RDMA_PIN_ALL),
- DEFINE_PROP_MIG_CAP("x-auto-converge", MIGRATION_CAPABILITY_AUTO_CONVERGE),
- DEFINE_PROP_MIG_CAP("x-events", MIGRATION_CAPABILITY_EVENTS),
- DEFINE_PROP_MIG_CAP("x-postcopy-ram", MIGRATION_CAPABILITY_POSTCOPY_RAM),
- DEFINE_PROP_MIG_CAP("x-postcopy-preempt",
- MIGRATION_CAPABILITY_POSTCOPY_PREEMPT),
- DEFINE_PROP_MIG_CAP("postcopy-blocktime",
- MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME),
- DEFINE_PROP_MIG_CAP("x-colo", MIGRATION_CAPABILITY_X_COLO),
- DEFINE_PROP_MIG_CAP("x-release-ram", MIGRATION_CAPABILITY_RELEASE_RAM),
- DEFINE_PROP_MIG_CAP("x-return-path", MIGRATION_CAPABILITY_RETURN_PATH),
- DEFINE_PROP_MIG_CAP("x-multifd", MIGRATION_CAPABILITY_MULTIFD),
- DEFINE_PROP_MIG_CAP("x-background-snapshot",
- MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT),
+ DEFINE_PROP_BOOL("x-xbzrle",
+ MigrationState, parameters.xbzrle, false),
+ DEFINE_PROP_BOOL("x-rdma-pin-all",
+ MigrationState, parameters.rdma_pin_all, false),
+ DEFINE_PROP_BOOL("x-auto-converge",
+ MigrationState, parameters.auto_converge, false),
+ DEFINE_PROP_BOOL("x-events",
+ MigrationState, parameters.events, false),
+ DEFINE_PROP_BOOL("x-postcopy-ram",
+ MigrationState, parameters.postcopy_ram, false),
+ DEFINE_PROP_BOOL("x-postcopy-preempt",
+ MigrationState, parameters.postcopy_preempt, false),
+ DEFINE_PROP_BOOL("postcopy-blocktime",
+ MigrationState, parameters.postcopy_blocktime, false),
+ DEFINE_PROP_BOOL("x-colo",
+ MigrationState, parameters.x_colo, false),
+ DEFINE_PROP_BOOL("x-release-ram",
+ MigrationState, parameters.release_ram, false),
+ DEFINE_PROP_BOOL("x-return-path",
+ MigrationState, parameters.return_path, false),
+ DEFINE_PROP_BOOL("x-multifd",
+ MigrationState, parameters.multifd, false),
+ DEFINE_PROP_BOOL("x-background-snapshot",
+ MigrationState, parameters.background_snapshot, false),
#ifdef CONFIG_LINUX
- DEFINE_PROP_MIG_CAP("x-zero-copy-send",
- MIGRATION_CAPABILITY_ZERO_COPY_SEND),
+ DEFINE_PROP_BOOL("x-zero-copy-send",
+ MigrationState, parameters.zero_copy_send, false),
#endif
- DEFINE_PROP_MIG_CAP("x-switchover-ack",
- MIGRATION_CAPABILITY_SWITCHOVER_ACK),
- DEFINE_PROP_MIG_CAP("x-dirty-limit", MIGRATION_CAPABILITY_DIRTY_LIMIT),
- DEFINE_PROP_MIG_CAP("mapped-ram", MIGRATION_CAPABILITY_MAPPED_RAM),
- DEFINE_PROP_MIG_CAP("x-ignore-shared",
- MIGRATION_CAPABILITY_X_IGNORE_SHARED),
+ DEFINE_PROP_BOOL("x-switchover-ack",
+ MigrationState, parameters.switchover_ack, false),
+ DEFINE_PROP_BOOL("x-dirty-limit",
+ MigrationState, parameters.dirty_limit, false),
+ DEFINE_PROP_BOOL("mapped-ram",
+ MigrationState, parameters.mapped_ram, false),
+ DEFINE_PROP_BOOL("x-ignore-shared",
+ MigrationState, parameters.x_ignore_shared, false),
};
const size_t migration_properties_count = ARRAY_SIZE(migration_properties);
@@ -306,7 +313,7 @@ bool migrate_auto_converge(void)
{
MigrationState *s = migrate_get_current();
- return s->capabilities[MIGRATION_CAPABILITY_AUTO_CONVERGE];
+ return s->parameters.auto_converge;
}
bool migrate_send_switchover_start(void)
@@ -320,144 +327,142 @@ bool migrate_background_snapshot(void)
{
MigrationState *s = migrate_get_current();
- return s->capabilities[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT];
+ return s->parameters.background_snapshot;
}
bool migrate_colo(void)
{
MigrationState *s = migrate_get_current();
- return s->capabilities[MIGRATION_CAPABILITY_X_COLO];
+ return s->parameters.x_colo;
}
bool migrate_dirty_bitmaps(void)
{
MigrationState *s = migrate_get_current();
- return s->capabilities[MIGRATION_CAPABILITY_DIRTY_BITMAPS];
+ return s->parameters.dirty_bitmaps;
}
bool migrate_dirty_limit(void)
{
MigrationState *s = migrate_get_current();
- return s->capabilities[MIGRATION_CAPABILITY_DIRTY_LIMIT];
+ return s->parameters.dirty_limit;
}
bool migrate_events(void)
{
MigrationState *s = migrate_get_current();
- return s->capabilities[MIGRATION_CAPABILITY_EVENTS];
+ return s->parameters.events;
}
bool migrate_mapped_ram(void)
{
MigrationState *s = migrate_get_current();
- return s->capabilities[MIGRATION_CAPABILITY_MAPPED_RAM];
+ return s->parameters.mapped_ram;
}
bool migrate_ignore_shared(void)
{
MigrationState *s = migrate_get_current();
- return s->capabilities[MIGRATION_CAPABILITY_X_IGNORE_SHARED];
+ return s->parameters.x_ignore_shared;
}
bool migrate_late_block_activate(void)
{
MigrationState *s = migrate_get_current();
- return s->capabilities[MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE];
+ return s->parameters.late_block_activate;
}
bool migrate_multifd(void)
{
MigrationState *s = migrate_get_current();
- return s->capabilities[MIGRATION_CAPABILITY_MULTIFD];
+ return s->parameters.multifd;
}
bool migrate_pause_before_switchover(void)
{
MigrationState *s = migrate_get_current();
- return s->capabilities[MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER];
+ return s->parameters.pause_before_switchover;
}
bool migrate_postcopy_blocktime(void)
{
MigrationState *s = migrate_get_current();
- return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME];
+ return s->parameters.postcopy_blocktime;
}
bool migrate_postcopy_preempt(void)
{
MigrationState *s = migrate_get_current();
- return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT];
+ return s->parameters.postcopy_preempt;
}
bool migrate_postcopy_ram(void)
{
MigrationState *s = migrate_get_current();
- return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_RAM];
+ return s->parameters.postcopy_ram;
}
bool migrate_rdma_pin_all(void)
{
MigrationState *s = migrate_get_current();
- return s->capabilities[MIGRATION_CAPABILITY_RDMA_PIN_ALL];
+ return s->parameters.rdma_pin_all;
}
bool migrate_release_ram(void)
{
MigrationState *s = migrate_get_current();
- return s->capabilities[MIGRATION_CAPABILITY_RELEASE_RAM];
+ return s->parameters.release_ram;
}
bool migrate_return_path(void)
{
MigrationState *s = migrate_get_current();
- return s->capabilities[MIGRATION_CAPABILITY_RETURN_PATH];
+ return s->parameters.return_path;
}
bool migrate_switchover_ack(void)
{
MigrationState *s = migrate_get_current();
- return s->capabilities[MIGRATION_CAPABILITY_SWITCHOVER_ACK];
+ return s->parameters.switchover_ack;
}
bool migrate_validate_uuid(void)
{
MigrationState *s = migrate_get_current();
- return s->capabilities[MIGRATION_CAPABILITY_VALIDATE_UUID];
+ return s->parameters.validate_uuid;
}
bool migrate_xbzrle(void)
{
MigrationState *s = migrate_get_current();
- return s->capabilities[MIGRATION_CAPABILITY_XBZRLE];
+ return s->parameters.xbzrle;
}
bool migrate_zero_copy_send(void)
{
MigrationState *s = migrate_get_current();
- return s->capabilities[MIGRATION_CAPABILITY_ZERO_COPY_SEND];
+ return s->parameters.zero_copy_send;
}
-/* pseudo capabilities */
-
bool migrate_multifd_flush_after_each_section(void)
{
MigrationState *s = migrate_get_current();
@@ -509,44 +514,6 @@ WriteTrackingSupport migrate_query_write_tracking(void)
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_XBZRLE,
- MIGRATION_CAPABILITY_X_COLO,
- MIGRATION_CAPABILITY_VALIDATE_UUID,
- MIGRATION_CAPABILITY_ZERO_COPY_SEND);
-
-/* Snapshot compatibility check list */
-static const
-INITIALIZE_MIGRATE_CAPS_SET(check_caps_savevm,
- MIGRATION_CAPABILITY_MULTIFD,
-);
-
static bool migrate_incoming_started(void)
{
return !!migration_incoming_get_current()->transport_data;
@@ -555,34 +522,28 @@ static bool migrate_incoming_started(void)
bool migrate_can_snapshot(Error **errp)
{
MigrationState *s = migrate_get_current();
- int i;
- for (i = 0; i < check_caps_savevm.size; i++) {
- int incomp_cap = check_caps_savevm.caps[i];
-
- if (s->capabilities[incomp_cap]) {
- error_setg(errp,
- "Snapshots are not compatible with %s",
- MigrationCapability_str(incomp_cap));
- return false;
- }
+ if (migrate_capability_get_compat(
+ &s->parameters, MIGRATION_CAPABILITY_MULTIFD)) {
+ error_setg(errp,
+ "Snapshots are not compatible with multifd");
+ return false;
}
return true;
}
-
-bool migrate_rdma_caps_check(bool *caps, Error **errp)
+bool migrate_rdma_caps_check(MigrationParameters *params, Error **errp)
{
- if (caps[MIGRATION_CAPABILITY_XBZRLE]) {
+ if (params->xbzrle) {
error_setg(errp, "RDMA and XBZRLE can't be used together");
return false;
}
- if (caps[MIGRATION_CAPABILITY_MULTIFD]) {
+ if (params->multifd) {
error_setg(errp, "RDMA and multifd can't be used together");
return false;
}
- if (caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) {
+ if (params->postcopy_ram) {
error_setg(errp, "RDMA and postcopy-ram can't be used together");
return false;
}
@@ -590,30 +551,23 @@ bool migrate_rdma_caps_check(bool *caps, Error **errp)
return true;
}
-/**
- * @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)
+bool migrate_caps_check(MigrationParameters *new, Error **errp)
{
- ERRP_GUARD();
+ MigrationState *s = migrate_get_current();
MigrationIncomingState *mis = migration_incoming_get_current();
+ bool postcopy_already_on = s->parameters.postcopy_ram;
+ ERRP_GUARD();
#ifdef CONFIG_REPLICATION
- if (new_caps[MIGRATION_CAPABILITY_X_COLO]) {
- if (!new_caps[MIGRATION_CAPABILITY_RETURN_PATH]) {
+ if (new->x_colo) {
+ if (!new->return_path) {
error_setg(errp, "Capability 'x-colo' requires capability "
"'return-path'");
return false;
}
}
#else
- if (new_caps[MIGRATION_CAPABILITY_X_COLO]) {
+ if (new->x_colo) {
error_setg(errp, "QEMU compiled without replication module"
" can't enable COLO");
error_append_hint(errp, "Please enable replication before COLO.\n");
@@ -621,27 +575,27 @@ bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp)
}
#endif
- if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) {
+ if (new->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] &&
+ if (!postcopy_already_on &&
runstate_check(RUN_STATE_INMIGRATE) &&
!postcopy_ram_supported_by_host(mis, errp)) {
error_prepend(errp, "Postcopy is not supported: ");
return false;
}
- if (new_caps[MIGRATION_CAPABILITY_X_IGNORE_SHARED]) {
+ if (new->x_ignore_shared) {
error_setg(errp, "Postcopy is not compatible with ignore-shared");
return false;
}
}
- if (new_caps[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT]) {
+ if (new->background_snapshot) {
WriteTrackingSupport wt_support;
- int idx;
+
/*
* Check if 'background-snapshot' capability is supported by
* host kernel and compatible with guest memory configuration.
@@ -657,41 +611,45 @@ bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp)
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;
- }
+ if (new->postcopy_ram ||
+ new->dirty_bitmaps ||
+ new->postcopy_blocktime ||
+ new->late_block_activate ||
+ new->return_path ||
+ new->multifd ||
+ new->pause_before_switchover ||
+ new->auto_converge ||
+ new->release_ram ||
+ new->rdma_pin_all ||
+ new->xbzrle ||
+ new->x_colo ||
+ new->validate_uuid ||
+ new->zero_copy_send) {
+ error_setg(errp,
+ "Background-snapshot is not compatible with "
+ "currently set capabilities");
+ return false;
}
}
#ifdef CONFIG_LINUX
- if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND] &&
- (!new_caps[MIGRATION_CAPABILITY_MULTIFD] ||
- new_caps[MIGRATION_CAPABILITY_XBZRLE] ||
- migrate_multifd_compression() ||
- migrate_tls())) {
+ if (new->zero_copy_send &&
+ (!new->multifd || new->xbzrle ||
+ migrate_multifd_compression() || migrate_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]) {
+ if (new->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]) {
+ if (new->postcopy_preempt) {
+ if (!new->postcopy_ram) {
error_setg(errp, "Postcopy preempt requires postcopy-ram");
return false;
}
@@ -703,22 +661,22 @@ bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp)
}
}
- if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) {
+ if (new->multifd) {
if (!migrate_multifd() && migrate_incoming_started()) {
error_setg(errp, "Multifd must be set before incoming starts");
return false;
}
}
- if (new_caps[MIGRATION_CAPABILITY_SWITCHOVER_ACK]) {
- if (!new_caps[MIGRATION_CAPABILITY_RETURN_PATH]) {
+ if (new->switchover_ack) {
+ if (!new->return_path) {
error_setg(errp, "Capability 'switchover-ack' requires capability "
"'return-path'");
return false;
}
}
- if (new_caps[MIGRATION_CAPABILITY_DIRTY_LIMIT]) {
- if (new_caps[MIGRATION_CAPABILITY_AUTO_CONVERGE]) {
+ if (new->dirty_limit) {
+ if (new->auto_converge) {
error_setg(errp, "dirty-limit conflicts with auto-converge"
" either of then available currently");
return false;
@@ -731,30 +689,29 @@ bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp)
}
}
- if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) {
- if (new_caps[MIGRATION_CAPABILITY_XBZRLE]) {
+ if (new->multifd) {
+ if (new->xbzrle) {
error_setg(errp, "Multifd is not compatible with xbzrle");
return false;
}
}
- if (new_caps[MIGRATION_CAPABILITY_MAPPED_RAM]) {
- if (new_caps[MIGRATION_CAPABILITY_XBZRLE]) {
+ if (new->mapped_ram) {
+ if (new->xbzrle) {
error_setg(errp,
"Mapped-ram migration is incompatible with xbzrle");
return false;
}
}
- if (new_caps[MIGRATION_CAPABILITY_MAPPED_RAM] &&
- new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) {
- if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) {
+ if (new->mapped_ram && new->postcopy_ram) {
+ if (new->multifd) {
error_setg(errp,
"Multifd is not supported with fast snapshot load");
return false;
}
- if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT]) {
+ if (new->postcopy_preempt) {
error_setg(
errp,
"Postcopy Preempt is incompatible with fast snapshot load");
@@ -772,7 +729,7 @@ bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp)
* On destination side, check the cases that capability is being set
* after incoming thread has started.
*/
- if (migrate_rdma() && !migrate_rdma_caps_check(new_caps, errp)) {
+ if (migrate_rdma() && !migrate_rdma_caps_check(new, errp)) {
return false;
}
return true;
@@ -890,39 +847,37 @@ MigrationCapabilityStatusList *qmp_query_migrate_capabilities(Error **errp)
for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
caps = g_malloc0(sizeof(*caps));
caps->capability = i;
- caps->state = s->capabilities[i];
+ caps->state = migrate_capability_get_compat(&s->parameters, i);
QAPI_LIST_APPEND(tail, caps);
}
return head;
}
-void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params,
+void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *capabilities,
Error **errp)
{
MigrationState *s = migrate_get_current();
- MigrationCapabilityStatusList *cap;
- bool new_caps[MIGRATION_CAPABILITY__MAX];
+ g_autoptr(MigrationParameters) params = NULL;
if (migration_is_running() || migration_in_colo_state()) {
error_setg(errp, "There's a migration process in progress");
return;
}
- memcpy(new_caps, s->capabilities, sizeof(new_caps));
- for (cap = params; cap; cap = cap->next) {
- new_caps[cap->value->capability] = cap->value->state;
- }
+ /*
+ * Capabilities validation needs to first copy from s->parameters
+ * in case the incoming capabilities have a capability that
+ * conflicts with another that's already set.
+ */
+ params = QAPI_CLONE(MigrationParameters, &s->parameters);
+ migrate_capabilities_set_compat(params, capabilities);
- if (!migrate_caps_check(s->capabilities, new_caps, errp)) {
+ if (!migrate_caps_check(params, errp)) {
return;
}
- for (cap = params; cap; cap = cap->next) {
- s->capabilities[cap->value->capability] = cap->value->state;
- }
-
- migrate_capabilities_set_compat(&s->parameters, params);
+ migrate_capabilities_set_compat(&s->parameters, capabilities);
}
/* parameters */
@@ -983,9 +938,8 @@ bool migrate_direct_io(void)
* isolated to the main migration thread while multifd channels
* process the aligned data with O_DIRECT enabled.
*/
- return s->parameters.direct_io &&
- s->capabilities[MIGRATION_CAPABILITY_MAPPED_RAM] &&
- s->capabilities[MIGRATION_CAPABILITY_MULTIFD];
+ return s->parameters.direct_io && s->parameters.mapped_ram &&
+ s->parameters.multifd;
}
uint64_t migrate_downtime_limit(void)
@@ -1555,6 +1509,9 @@ bool migrate_params_check(MigrationParameters *params, Error **errp)
!is_power_of_2(params->x_rdma_chunk_size))) {
error_setg(errp, "Option x_rdma_chunk_size expects "
"a power of 2 in the range 1MiB to 1024MiB");
+ }
+
+ if (!migrate_caps_check(params, errp)) {
return false;
}
@@ -1578,20 +1535,6 @@ void qmp_migrate_set_parameters(MigrationParameters *input, Error **errp)
tls_opt_to_str(input->tls_hostname);
tls_opt_to_str(input->tls_authz);
- /*
- * FIXME: Temporarily while migrate_caps_check is not
- * converted to look at s->parameters. Will be gone the end of
- * the series.
- */
- bool new_caps[MIGRATION_CAPABILITY__MAX] = { 0 };
- for (int i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
- new_caps[i] = migrate_capability_get_compat(cur, i);
- }
- if (!migrate_caps_check(migrate_get_current()->capabilities, new_caps,
- errp)) {
- return;
- }
-
/* merge input on top of current */
if (!migrate_params_merge(cur, input, &new, errp)) {
return;
@@ -1,5 +1,5 @@
/*
- * QEMU migration capabilities
+ * QEMU migration options
*
* Copyright (c) 2012-2023 Red Hat Inc
*
@@ -23,8 +23,6 @@
extern const Property migration_properties[];
extern const size_t migration_properties_count;
-/* capabilities */
-
bool migrate_auto_converge(void);
bool migrate_colo(void);
bool migrate_dirty_bitmaps(void);
@@ -43,22 +41,12 @@ bool migrate_validate_uuid(void);
bool migrate_xbzrle(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_multifd_flush_after_each_section(void);
bool migrate_postcopy(void);
bool migrate_rdma(void);
bool migrate_tls(void);
-/* capabilities helpers */
-
-bool migrate_rdma_caps_check(bool *caps, Error **errp);
-bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp);
+bool migrate_rdma_caps_check(MigrationParameters *config, Error **errp);
bool migrate_can_snapshot(Error **errp);
/* parameters */
@@ -89,8 +77,6 @@ uint64_t migrate_xbzrle_cache_size(void);
ZeroPageDetection migrate_zero_page_detection(void);
uint64_t migrate_rdma_chunk_size(void);
-/* parameters helpers */
-
bool migrate_params_check(MigrationParameters *params, Error **errp);
void migrate_params_init(MigrationParameters *params);
bool migrate_params_free(MigrationParameters *params, Error **errp);
@@ -99,4 +85,5 @@ void migrate_capability_set_compat(MigrationParameters *params, int i,
bool val);
void migrate_capabilities_set_compat(MigrationParameters *params,
MigrationCapabilityStatusList *caps);
+bool migrate_caps_check(MigrationParameters *new, Error **errp);
#endif
@@ -291,7 +291,8 @@ static uint32_t get_validatable_capabilities_count(void)
uint32_t result = 0;
int i;
for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
- if (should_validate_capability(i) && s->capabilities[i]) {
+ if (should_validate_capability(i) &&
+ migrate_capability_get_compat(&s->parameters, i)) {
result++;
}
}
@@ -313,7 +314,8 @@ static bool configuration_pre_save(void *opaque, Error **errp)
state->capabilities = g_renew(MigrationCapability, state->capabilities,
state->caps_count);
for (i = j = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
- if (should_validate_capability(i) && s->capabilities[i]) {
+ if (should_validate_capability(i) &&
+ migrate_capability_get_compat(&s->parameters, i)) {
state->capabilities[j++] = i;
}
}
@@ -362,7 +364,7 @@ static bool configuration_validate_capabilities(SaveState *state)
continue;
}
source_state = test_bit(i, source_caps_bm);
- target_state = s->capabilities[i];
+ target_state = migrate_capability_get_compat(&s->parameters, i);
if (source_state != target_state) {
error_report("Capability %s is %s, but received capability is %s",
MigrationCapability_str(i),
@@ -53,6 +53,147 @@ HMPTestData test_cases[] = {
/* bool */
TEST("cpu-throttle-tailslow", "on", "on"),
TEST("direct-io", "on", "on"),
+ TEST("events", "on", "on"),
+
+ /* bool, with dependencies */
+
+ /*
+ * background-snapshot:
+ * rejects dirty-bitmaps
+ * rejects postcopy-blocktime
+ * rejects late-block-activate
+ * rejects multifd
+ * rejects pause-before-switchover
+ * rejects auto-converge
+ * rejects release-ram
+ * rejects rdma-pin-all
+ * rejects validate-uuid
+ * rejects zero-copy-send
+ * rejects postcopy-ram
+ */
+ TEST("background-snapshot", "on", "on"),
+ TEST("dirty-bitmaps", "on", BG_SNAP_MSG),
+ TEST("postcopy-blocktime", "on", BG_SNAP_MSG),
+ TEST("late-block-activate", "on", BG_SNAP_MSG),
+ TEST("multifd", "on", BG_SNAP_MSG),
+ TEST("pause-before-switchover", "on", BG_SNAP_MSG),
+ TEST("auto-converge", "on", BG_SNAP_MSG),
+ TEST("release-ram", "on", BG_SNAP_MSG),
+ TEST("rdma-pin-all", "on", BG_SNAP_MSG),
+ TEST("validate-uuid", "on", BG_SNAP_MSG),
+ TEST("zero-copy-send", "on", BG_SNAP_MSG),
+ TEST("postcopy-ram", "on", BG_SNAP_MSG),
+ TEST("background-snapshot", "off", "off"),
+
+ TEST("dirty-bitmaps", "on", "on"),
+ TEST("postcopy-blocktime", "on", "on"),
+ TEST("late-block-activate", "on", "on"),
+ TEST("pause-before-switchover", "on", "on"),
+ TEST("auto-converge", "on", "on"),
+ TEST("release-ram", "on", "on"),
+ TEST("rdma-pin-all", "on", "on"),
+ TEST("validate-uuid", "on", "on"),
+
+ /*
+ * postcopy-preempt
+ * requires postcopy-ram:
+ */
+ TEST("postcopy-preempt", "on",
+ "Error: Postcopy preempt requires postcopy-ram"),
+
+ /*
+ * postcopy-ram:
+ * required by postcopy-preempt
+ * rejected by x-ignore-shared
+ * rejected by background-snapshot
+ * rejected by mapped-ram
+ */
+ TEST("postcopy-ram", "on", "on"),
+ TEST("postcopy-preempt", "on", "on"),
+ TEST("x-ignore-shared", "on",
+ "Error: Postcopy is not compatible with ignore-shared"),
+ TEST("background-snapshot", "on", BG_SNAP_MSG),
+ TEST("mapped-ram", "on",
+ "Error: Postcopy Preempt is incompatible with fast snapshot load"),
+ TEST("postcopy-ram", "off",
+ "Error: Postcopy preempt requires postcopy-ram"),
+ TEST("postcopy-preempt", "off", "off"),
+ TEST("postcopy-ram", "off", "off"),
+
+ /*
+ * x-ignore-shared:
+ * rejected by postcopy-ram
+ */
+ TEST("x-ignore-shared", "on", "on"),
+ TEST("postcopy-ram", "on",
+ "Error: Postcopy is not compatible with ignore-shared"),
+ TEST("x-ignore-shared", "off", "off"),
+
+ /*
+ * return-path:
+ * required by x-colo
+ * required by switchover-ack
+ * rejected by background-snapshot
+ */
+ TEST("return-path", "on", "on"),
+ TEST("x-colo", "on", "on"),
+ TEST("switchover-ack", "on", "on"),
+ TEST("background-snapshot", "on", BG_SNAP_MSG),
+
+ TEST("return-path", "off",
+ "Error: Capability 'x-colo' requires capability 'return-path'"),
+ TEST("x-colo", "off", "off"),
+
+ TEST("return-path", "off",
+ "Error: Capability 'switchover-ack' requires capability "
+ "'return-path'"),
+ TEST("switchover-ack", "off", "off"),
+ TEST("return-path", "off", "off"),
+
+ TEST("x-colo", "on",
+ "Error: Capability 'x-colo' requires capability 'return-path'"),
+ TEST("switchover-ack", "on", "Error: Capability 'switchover-ack' requires "
+ "capability 'return-path'"),
+
+ /*
+ * xbzrle:
+ * rejected by multifd
+ */
+ TEST("xbzrle", "on", "on"),
+ TEST("multifd", "on", "Error: Multifd is not compatible with xbzrle"),
+ TEST("xbzrle", "off", "off"),
+
+ /*
+ * multifd:
+ * rejected by xbzrle
+ * required by zero-copy-send
+ */
+ TEST("multifd", "on", "on"),
+ TEST("xbzrle", "on", "Error: Multifd is not compatible with xbzrle"),
+ TEST("zero-copy-send", "on", "on"),
+ TEST("multifd", "off", "Error: Zero copy only available for "
+ "non-compressed non-TLS multifd migration"),
+ TEST("zero-copy-send", "off", "off"),
+ TEST("multifd", "off", "off"),
+
+ /*
+ * auto-converge:
+ * rejected by dirty-limit
+ */
+ TEST("auto-converge", "on", "on"),
+ TEST("dirty-limit", "on",
+ "Error: dirty-limit conflicts with auto-converge "
+ "either of then available currently"),
+ TEST("auto-converge", "off", "off"),
+
+ /*
+ * dirty-limit:
+ * rejected by auto-converge
+ * requires KVM acceleration
+ */
+ TEST("dirty-limit", "on",
+ "Error: dirty-limit requires KVM with accelerator "
+ "property 'dirty-ring-size' set"),
/* uint64_t */
TEST("announce-initial", "60", "60"),