From 2833c59b947cf909020c4d6194aac35f383e832b Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 5 Apr 2017 18:32:37 +0200 Subject: migration: Create block capability Create one capability for block migration and one parameter for incremental block migration. Signed-off-by: Juan Quintela Reviewed-by: Eric Blake --- - address all Markus comments - use Markus and Eric text descriptions - change logic another time - improve text messages --- migration/migration.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) (limited to 'migration') diff --git a/migration/migration.c b/migration/migration.c index 0304c013f3..c13c0a293e 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -592,6 +592,8 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp) 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; return params; } @@ -900,6 +902,9 @@ void qmp_migrate_set_parameters(MigrationParameters *params, Error **errp) colo_checkpoint_notify(s); } } + if (params->has_block_incremental) { + s->parameters.block_incremental = params->block_incremental; + } } @@ -935,6 +940,33 @@ void migrate_set_state(int *state, int old_state, int new_state) } } +void migrate_set_block_enabled(bool value, Error **errp) +{ + MigrationCapabilityStatusList *cap; + + cap = g_new0(MigrationCapabilityStatusList, 1); + cap->value = g_new0(MigrationCapabilityStatus, 1); + cap->value->capability = MIGRATION_CAPABILITY_BLOCK; + cap->value->state = 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; +} + +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_set_block_incremental(s, false); + s->must_remove_block_options = false; + } +} + static void migrate_fd_cleanup(void *opaque) { MigrationState *s = opaque; @@ -967,6 +999,7 @@ static void migrate_fd_cleanup(void *opaque) } notifier_list_notify(&migration_state_notifiers, s); + block_cleanup_parameters(s); } void migrate_fd_error(MigrationState *s, const Error *error) @@ -979,6 +1012,7 @@ void migrate_fd_error(MigrationState *s, const Error *error) s->error = error_copy(error); } notifier_list_notify(&migration_state_notifiers, s); + block_cleanup_parameters(s); } static void migrate_fd_cancel(MigrationState *s) @@ -1020,6 +1054,7 @@ static void migrate_fd_cancel(MigrationState *s) s->block_inactive = false; } } + block_cleanup_parameters(s); } void add_migration_state_change_notifier(Notifier *notify) @@ -1207,6 +1242,24 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, return; } + if ((has_blk && blk) || (has_inc && inc)) { + if (migrate_use_block() || migrate_use_block_incremental()) { + error_setg(errp, "Command options are incompatible with " + "current migration capabilities"); + return; + } + migrate_set_block_enabled(true, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + s->must_remove_block_options = true; + } + + if (has_inc && inc) { + migrate_set_block_incremental(s, true); + } + s = migrate_init(¶ms); if (strstart(uri, "tcp:", &p)) { @@ -1404,6 +1457,24 @@ int64_t migrate_xbzrle_cache_size(void) return s->xbzrle_cache_size; } +bool migrate_use_block(void) +{ + MigrationState *s; + + s = migrate_get_current(); + + return s->enabled_capabilities[MIGRATION_CAPABILITY_BLOCK]; +} + +bool migrate_use_block_incremental(void) +{ + MigrationState *s; + + s = migrate_get_current(); + + return s->parameters.block_incremental; +} + /* migration thread support */ /* * Something bad happened to the RP stream, mark an error -- cgit v1.2.3