diff --git a/migration/migration.c b/migration/migration.c index 915c8cc11f224f70bf50eb0e191043b93a53f495..74099b361fed98f823f65acccbe788dbe7e07840 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -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) { + cap_list[cap->value->capability] = cap->value->state; + } + #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; + 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 (migrate_postcopy_ram()) { - if (migrate_use_compression()) { + 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; + } } /*