Commit 6b587af5ec for qemu.org

commit 6b587af5ec9d83e48598db1bc3ba7fcf1512f2dc
Author: Fabiano Rosas <farosas@suse.de>
Date:   Fri Jan 23 11:16:41 2026 -0300

    migration: Fold migration_cleanup() into migration_connect_error_propagate()

    Whenever an error occurs between migrate_init() and the start of
    migration_thread, do cleanup immediately.

    This allows the special casing for resume to be removed from
    migration_connect(), that check is now done at
    migration_connect_error_propagate() which already had a case for
    resume.

    The cleanup at qmp_migrate_finish_cb can also be removed because it
    will always be reached either via the error path at
    qmp_migrate_finish->migration_connect_error_propagate or via the
    migrate_cleanup_bh.

    The yank_unregister_instance at qmp_migrate() is now replaced by the
    one at migration_cleanup().

    Reviewed-by: Peter Xu <peterx@redhat.com>
    Reviewed-by: Prasad Pandit <pjp@fedoraproject.org>
    Link: https://lore.kernel.org/qemu-devel/20260123141656.6765-12-farosas@suse.de
    Signed-off-by: Fabiano Rosas <farosas@suse.de>

diff --git a/migration/migration.c b/migration/migration.c
index fd67076b1d..a78c2f4840 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -1573,15 +1573,21 @@ static void migration_connect_error_propagate(MigrationState *s, Error *error)
 {
     MigrationStatus current = s->state;
     MigrationStatus next = MIGRATION_STATUS_NONE;
+    bool resume = false;

     switch (current) {
     case MIGRATION_STATUS_SETUP:
         next = MIGRATION_STATUS_FAILED;
         break;

+    case MIGRATION_STATUS_POSTCOPY_PAUSED:
+        resume = true;
+        break;
+
     case MIGRATION_STATUS_POSTCOPY_RECOVER_SETUP:
         /* Never fail a postcopy migration; switch back to PAUSED instead */
         next = MIGRATION_STATUS_POSTCOPY_PAUSED;
+        resume = true;
         break;

     case MIGRATION_STATUS_CANCELLING:
@@ -1606,6 +1612,10 @@ static void migration_connect_error_propagate(MigrationState *s, Error *error)
     }

     migrate_error_propagate(s, error);
+
+    if (!resume) {
+        migration_cleanup(s);
+    }
 }

 void migration_cancel(void)
@@ -2208,9 +2218,6 @@ static gboolean qmp_migrate_finish_cb(QIOChannel *channel,
     MigrationAddress *addr = opaque;

     qmp_migrate_finish(addr, NULL);
-
-    cpr_state_close();
-    migrate_hup_delete(migrate_get_current());
     qapi_free_MigrationAddress(addr);
     return G_SOURCE_REMOVE;
 }
@@ -2219,7 +2226,6 @@ void qmp_migrate(const char *uri, bool has_channels,
                  MigrationChannelList *channels,
                  bool has_resume, bool resume, Error **errp)
 {
-    Error *local_err = NULL;
     MigrationState *s = migrate_get_current();
     g_autoptr(MigrationChannel) channel = NULL;
     MigrationAddress *addr = NULL;
@@ -2276,6 +2282,13 @@ void qmp_migrate(const char *uri, bool has_channels,
         return;
     }

+    /*
+     * The migrate_prepare() above calls migrate_init(). From this
+     * point on, until the end of migration, make sure any failures
+     * eventually result in a call to migration_cleanup().
+     */
+    Error *local_err = NULL;
+
     if (!cpr_state_save(cpr_channel, &local_err)) {
         goto out;
     }
@@ -2300,7 +2313,6 @@ void qmp_migrate(const char *uri, bool has_channels,

 out:
     if (local_err) {
-        yank_unregister_instance(MIGRATION_YANK_INSTANCE);
         migration_connect_error_propagate(s, error_copy(local_err));
         error_propagate(errp, local_err);
     }
@@ -4018,9 +4030,6 @@ void migration_connect(MigrationState *s, Error *error_in)
     s->expected_downtime = migrate_downtime_limit();
     if (error_in) {
         migration_connect_error_propagate(s, error_in);
-        if (!resume) {
-            migration_cleanup(s);
-        }
         if (s->error) {
             error_report_err(error_copy(s->error));
         }
@@ -4099,7 +4108,6 @@ void migration_connect(MigrationState *s, Error *error_in)

 fail:
     migration_connect_error_propagate(s, local_err);
-    migration_cleanup(s);
     if (s->error) {
         error_report_err(error_copy(s->error));
     }