From 2f8ccc5d58c6493670a32470432dc229f35411b6 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Fri, 23 Jan 2026 11:16:39 -0300 Subject: [PATCH] migration: Expand migration_connect_error_propagate to cover cancelling Cover the CANCELLING state in migration_connect_error_propagate() and use it to funnel errors from migrate_prepare() until the end of migration_connect(). Reviewed-by: Peter Xu Reviewed-by: Prasad Pandit Link: https://lore.kernel.org/qemu-devel/20260123141656.6765-10-farosas@suse.de Signed-off-by: Fabiano Rosas --- migration/migration.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/migration/migration.c b/migration/migration.c index 000f113307..a83edb39a0 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -1572,18 +1572,25 @@ static void migrate_error_free(MigrationState *s) static void migration_connect_error_propagate(MigrationState *s, Error *error) { MigrationStatus current = s->state; - MigrationStatus next; - - assert(s->to_dst_file == NULL); + MigrationStatus next = MIGRATION_STATUS_NONE; switch (current) { case MIGRATION_STATUS_SETUP: next = MIGRATION_STATUS_FAILED; break; + case MIGRATION_STATUS_POSTCOPY_RECOVER_SETUP: /* Never fail a postcopy migration; switch back to PAUSED instead */ next = MIGRATION_STATUS_POSTCOPY_PAUSED; break; + + case MIGRATION_STATUS_CANCELLING: + /* + * Don't move out of CANCELLING, the only valid transition is to + * CANCELLED, at migration_cleanup(). + */ + break; + default: /* * This really shouldn't happen. Just be careful to not crash a VM @@ -1594,7 +1601,10 @@ static void migration_connect_error_propagate(MigrationState *s, Error *error) return; } - migrate_set_state(&s->state, current, next); + if (next) { + migrate_set_state(&s->state, current, next); + } + migrate_error_propagate(s, error); } @@ -4098,10 +4108,7 @@ void migration_connect(MigrationState *s, Error *error_in) return; fail: - migrate_error_propagate(s, error_copy(local_err)); - if (s->state != MIGRATION_STATUS_CANCELLING) { - migrate_set_state(&s->state, s->state, MIGRATION_STATUS_FAILED); - } + migration_connect_error_propagate(s, local_err); migration_cleanup(s); if (s->error) { error_report_err(error_copy(s->error));