migration: provide migrate_caps_check()

Abstract helper function to check migration capabilities (from the old
qmp_migrate_set_capabilities).  Prepare to be used somewhere else.

There is side effect on the change: when applying the capabilities, we
were skipping the invalid ones, but still applying the valid ones (if
they are provided in the same QMP request). After this refactoring,
we'll ignore all the capabilities if we detected invalid setup along the
way. However, I don't think it is a problem since general users should
not provide anything invalid after all.

Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
Message-Id: <1500349150-13240-9-git-send-email-peterx@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
This commit is contained in:
Peter Xu 2017-07-18 11:39:08 +08:00 committed by Juan Quintela
parent fd198f9002
commit 4a84214ebe

View file

@ -588,43 +588,49 @@ MigrationInfo *qmp_query_migrate(Error **errp)
return info;
}
void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params,
Error **errp)
/**
* @migration_caps_check - check capability validity
*
* @cap_list: old capability list, array of bool
* @params: new capabilities to be applied soon
* @errp: set *errp if the check failed, with reason
*
* Returns true if check passed, otherwise false.
*/
static bool migrate_caps_check(bool *cap_list,
MigrationCapabilityStatusList *params,
Error **errp)
{
MigrationState *s = migrate_get_current();
MigrationCapabilityStatusList *cap;
bool old_postcopy_cap = migrate_postcopy_ram();
bool old_postcopy_cap;
if (migration_is_setup_or_active(s->state)) {
error_setg(errp, QERR_MIGRATION_ACTIVE);
return;
}
old_postcopy_cap = cap_list[MIGRATION_CAPABILITY_POSTCOPY_RAM];
for (cap = params; cap; cap = cap->next) {
#ifndef CONFIG_LIVE_BLOCK_MIGRATION
if (cap->value->capability == MIGRATION_CAPABILITY_BLOCK
&& cap->value->state) {
error_setg(errp, "QEMU compiled without old-style (blk/-b, inc/-i) "
"block migration");
error_append_hint(errp, "Use drive_mirror+NBD instead.\n");
continue;
}
#endif
s->enabled_capabilities[cap->value->capability] = cap->value->state;
cap_list[cap->value->capability] = cap->value->state;
}
if (migrate_postcopy_ram()) {
if (migrate_use_compression()) {
#ifndef CONFIG_LIVE_BLOCK_MIGRATION
if (cap_list[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
if (cap_list[MIGRATION_CAPABILITY_POSTCOPY_RAM]) {
if (cap_list[MIGRATION_CAPABILITY_COMPRESS]) {
/* The decompression threads asynchronously write into RAM
* rather than use the atomic copies needed to avoid
* userfaulting. It should be possible to fix the decompression
* threads for compatibility in future.
*/
error_report("Postcopy is not currently compatible with "
"compression");
s->enabled_capabilities[MIGRATION_CAPABILITY_POSTCOPY_RAM] =
false;
error_setg(errp, "Postcopy is not currently compatible "
"with compression");
return false;
}
/* 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.
@ -634,11 +640,32 @@ void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params,
/* postcopy_ram_supported_by_host will have emitted a more
* detailed message
*/
error_report("Postcopy is not supported");
s->enabled_capabilities[MIGRATION_CAPABILITY_POSTCOPY_RAM] =
false;
error_setg(errp, "Postcopy is not supported");
return false;
}
}
return true;
}
void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params,
Error **errp)
{
MigrationState *s = migrate_get_current();
MigrationCapabilityStatusList *cap;
if (migration_is_setup_or_active(s->state)) {
error_setg(errp, QERR_MIGRATION_ACTIVE);
return;
}
if (!migrate_caps_check(s->enabled_capabilities, params, errp)) {
return;
}
for (cap = params; cap; cap = cap->next) {
s->enabled_capabilities[cap->value->capability] = cap->value->state;
}
}
/*