aboutsummaryrefslogtreecommitdiff
path: root/migration
diff options
context:
space:
mode:
Diffstat (limited to 'migration')
-rw-r--r--migration/migration.c25
-rw-r--r--migration/savevm.c13
-rw-r--r--migration/savevm.h1
3 files changed, 37 insertions, 2 deletions
diff --git a/migration/migration.c b/migration/migration.c
index 38efaeee94..a5ddf43559 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -174,6 +174,8 @@ INITIALIZE_MIGRATE_CAPS_SET(check_caps_background_snapshot,
static MigrationState *current_migration;
static MigrationIncomingState *current_incoming;
+static GSList *migration_blockers;
+
static bool migration_object_check(MigrationState *ms, Error **errp);
static int migration_maybe_pause(MigrationState *s,
int *current_active_state,
@@ -1074,6 +1076,27 @@ static void fill_source_migration_info(MigrationInfo *info)
{
MigrationState *s = migrate_get_current();
+ info->blocked = migration_is_blocked(NULL);
+ info->has_blocked_reasons = info->blocked;
+ info->blocked_reasons = NULL;
+ if (info->blocked) {
+ GSList *cur_blocker = migration_blockers;
+
+ /*
+ * There are two types of reasons a migration might be blocked;
+ * a) devices marked in VMState as non-migratable, and
+ * b) Explicit migration blockers
+ * We need to add both of them here.
+ */
+ qemu_savevm_non_migratable_list(&info->blocked_reasons);
+
+ while (cur_blocker) {
+ QAPI_LIST_PREPEND(info->blocked_reasons,
+ g_strdup(error_get_pretty(cur_blocker->data)));
+ cur_blocker = g_slist_next(cur_blocker);
+ }
+ }
+
switch (s->state) {
case MIGRATION_STATUS_NONE:
/* no migration has happened ever */
@@ -2025,8 +2048,6 @@ void migrate_init(MigrationState *s)
s->threshold_size = 0;
}
-static GSList *migration_blockers;
-
int migrate_add_blocker(Error *reason, Error **errp)
{
if (only_migratable) {
diff --git a/migration/savevm.c b/migration/savevm.c
index d5bf53388f..1178c6ca90 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -1154,6 +1154,19 @@ bool qemu_savevm_state_blocked(Error **errp)
return false;
}
+void qemu_savevm_non_migratable_list(strList **reasons)
+{
+ SaveStateEntry *se;
+
+ QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
+ if (se->vmsd && se->vmsd->unmigratable) {
+ QAPI_LIST_PREPEND(*reasons,
+ g_strdup_printf("non-migratable device: %s",
+ se->idstr));
+ }
+ }
+}
+
void qemu_savevm_state_header(QEMUFile *f)
{
trace_savevm_state_header();
diff --git a/migration/savevm.h b/migration/savevm.h
index aaee2528ed..6461342cb4 100644
--- a/migration/savevm.h
+++ b/migration/savevm.h
@@ -30,6 +30,7 @@
#define QEMU_VM_SECTION_FOOTER 0x7e
bool qemu_savevm_state_blocked(Error **errp);
+void qemu_savevm_non_migratable_list(strList **reasons);
void qemu_savevm_state_setup(QEMUFile *f);
bool qemu_savevm_state_guest_unplug_pending(void);
int qemu_savevm_state_resume_prepare(MigrationState *s);