diff options
Diffstat (limited to 'migration/migration.c')
| -rw-r--r-- | migration/migration.c | 61 |
1 files changed, 58 insertions, 3 deletions
diff --git a/migration/migration.c b/migration/migration.c index f498ab84f2..2766d2f586 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -1006,6 +1006,16 @@ static void migrate_fd_cancel(MigrationState *s) if (s->state == MIGRATION_STATUS_CANCELLING && f) { qemu_file_shutdown(f); } + if (s->state == MIGRATION_STATUS_CANCELLING && s->block_inactive) { + Error *local_err = NULL; + + bdrv_invalidate_cache_all(&local_err); + if (local_err) { + error_report_err(local_err); + } else { + s->block_inactive = false; + } + } } void add_migration_state_change_notifier(Notifier *notify) @@ -1044,6 +1054,31 @@ bool migration_in_postcopy_after_devices(MigrationState *s) return migration_in_postcopy(s) && s->postcopy_after_devices; } +bool migration_is_idle(MigrationState *s) +{ + if (!s) { + s = migrate_get_current(); + } + + switch (s->state) { + case MIGRATION_STATUS_NONE: + case MIGRATION_STATUS_CANCELLED: + case MIGRATION_STATUS_COMPLETED: + case MIGRATION_STATUS_FAILED: + return true; + case MIGRATION_STATUS_SETUP: + case MIGRATION_STATUS_CANCELLING: + case MIGRATION_STATUS_ACTIVE: + case MIGRATION_STATUS_POSTCOPY_ACTIVE: + case MIGRATION_STATUS_COLO: + return false; + case MIGRATION_STATUS__MAX: + g_assert_not_reached(); + } + + return false; +} + MigrationState *migrate_init(const MigrationParams *params) { MigrationState *s = migrate_get_current(); @@ -1086,9 +1121,24 @@ MigrationState *migrate_init(const MigrationParams *params) static GSList *migration_blockers; -void migrate_add_blocker(Error *reason) +int migrate_add_blocker(Error *reason, Error **errp) { - migration_blockers = g_slist_prepend(migration_blockers, reason); + if (only_migratable) { + error_propagate(errp, error_copy(reason)); + error_prepend(errp, "disallowing migration blocker " + "(--only_migratable) for: "); + return -EACCES; + } + + if (migration_is_idle(NULL)) { + migration_blockers = g_slist_prepend(migration_blockers, reason); + return 0; + } + + error_propagate(errp, error_copy(reason)); + error_prepend(errp, "disallowing migration blocker (migration in " + "progress) for: "); + return -EBUSY; } void migrate_del_blocker(Error *reason) @@ -1705,6 +1755,7 @@ static void migration_completion(MigrationState *s, int current_active_state, if (ret >= 0) { qemu_file_set_rate_limit(s->to_dst_file, INT64_MAX); qemu_savevm_state_complete_precopy(s->to_dst_file, false); + s->block_inactive = true; } } qemu_mutex_unlock_iothread(); @@ -1755,10 +1806,14 @@ fail_invalidate: if (s->state == MIGRATION_STATUS_ACTIVE) { Error *local_err = NULL; + qemu_mutex_lock_iothread(); bdrv_invalidate_cache_all(&local_err); if (local_err) { error_report_err(local_err); + } else { + s->block_inactive = false; } + qemu_mutex_unlock_iothread(); } fail: @@ -1969,7 +2024,7 @@ void migrate_fd_connect(MigrationState *s) } migrate_compress_threads_create(); - qemu_thread_create(&s->thread, "migration", migration_thread, s, + qemu_thread_create(&s->thread, "live_migration", migration_thread, s, QEMU_THREAD_JOINABLE); s->migration_thread_running = true; } |