[PATCH v2 18/25] migration: Move channel code to channel.c

Fabiano Rosas posted 25 patches 3 days, 14 hours ago
Maintainers: Peter Xu <peterx@redhat.com>, Fabiano Rosas <farosas@suse.de>, Mark Kanda <mark.kanda@oracle.com>, Ben Chaney <bchaney@akamai.com>, Li Zhijian <lizhijian@fujitsu.com>
[PATCH v2 18/25] migration: Move channel code to channel.c
Posted by Fabiano Rosas 3 days, 14 hours ago
Move the code responsible for the various channels connection into
channel.c. This is all executed before the migration_thread and
process_incoming_migration_co are running, so it helps the reasoning
to have them out of migration.c.

migration_ioc_process_incoming becomes migration_channel_identify
which is more in line with what the function does.

Signed-off-by: Fabiano Rosas <farosas@suse.de>
---
 migration/channel.c   | 99 ++++++++++++++++++++++++++++++++++++++++++-
 migration/channel.h   |  4 ++
 migration/migration.c | 96 -----------------------------------------
 migration/migration.h |  2 -
 migration/rdma.c      |  1 +
 5 files changed, 103 insertions(+), 99 deletions(-)

diff --git a/migration/channel.c b/migration/channel.c
index 8abcb54447..a6608c5f08 100644
--- a/migration/channel.c
+++ b/migration/channel.c
@@ -14,13 +14,110 @@
 #include "channel.h"
 #include "tls.h"
 #include "migration.h"
+#include "multifd.h"
+#include "savevm.h"
 #include "trace.h"
+#include "options.h"
 #include "qapi/error.h"
 #include "io/channel-tls.h"
 #include "io/channel-socket.h"
 #include "qemu/yank.h"
 #include "yank_functions.h"
 
+bool migration_has_main_and_multifd_channels(void)
+{
+    MigrationIncomingState *mis = migration_incoming_get_current();
+    if (!mis->from_src_file) {
+        /* main channel not established */
+        return false;
+    }
+
+    if (migrate_multifd() && !multifd_recv_all_channels_created()) {
+        return false;
+    }
+
+    /* main and all multifd channels are established */
+    return true;
+}
+
+/**
+ * @migration_has_all_channels: We have received all channels that we need
+ *
+ * Returns true when we have got connections to all the channels that
+ * we need for migration.
+ */
+bool migration_has_all_channels(void)
+{
+    if (!migration_has_main_and_multifd_channels()) {
+        return false;
+    }
+
+    MigrationIncomingState *mis = migration_incoming_get_current();
+    if (migrate_postcopy_preempt() && !mis->postcopy_qemufile_dst) {
+        return false;
+    }
+
+    return true;
+}
+
+static int migration_channel_identify(MigrationIncomingState *mis,
+                                      QIOChannel *ioc, Error **errp)
+{
+    int channel = CH_NONE;
+    uint32_t channel_magic = 0;
+    int ret = 0;
+
+    if (!migration_has_main_and_multifd_channels()) {
+        if (qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_READ_MSG_PEEK)) {
+            /*
+             * With multiple channels, it is possible that we receive channels
+             * out of order on destination side, causing incorrect mapping of
+             * source channels on destination side. Check channel MAGIC to
+             * decide type of channel. Please note this is best effort,
+             * postcopy preempt channel does not send any magic number so
+             * avoid it for postcopy live migration. Also tls live migration
+             * already does tls handshake while initializing main channel so
+             * with tls this issue is not possible.
+             */
+            ret = migration_channel_read_peek(ioc, (void *)&channel_magic,
+                                              sizeof(channel_magic), errp);
+            if (ret != 0) {
+                goto out;
+            }
+
+            channel_magic = be32_to_cpu(channel_magic);
+            if (channel_magic == QEMU_VM_FILE_MAGIC) {
+                channel = CH_MAIN;
+            } else if (channel_magic == MULTIFD_MAGIC) {
+                assert(migrate_multifd());
+                channel = CH_MULTIFD;
+            } else if (!mis->from_src_file &&
+                        mis->state == MIGRATION_STATUS_POSTCOPY_PAUSED) {
+                /* reconnect main channel for postcopy recovery */
+                channel = CH_MAIN;
+            } else {
+                error_setg(errp, "unknown channel magic: %u", channel_magic);
+            }
+        } else if (mis->from_src_file && migrate_multifd()) {
+            /*
+             * Non-peekable channels like tls/file are processed as
+             * multifd channels when multifd is enabled.
+             */
+            channel = CH_MULTIFD;
+        } else if (!mis->from_src_file) {
+            channel = CH_MAIN;
+        } else {
+            error_setg(errp, "non-peekable channel used without multifd");
+        }
+    } else {
+        assert(migrate_postcopy_preempt());
+        channel = CH_POSTCOPY;
+    }
+
+out:
+    return channel;
+}
+
 /**
  * @migration_channel_process_incoming - Create new incoming migration channel
  *
@@ -42,7 +139,7 @@ void migration_channel_process_incoming(QIOChannel *ioc)
         migration_tls_channel_process_incoming(ioc, &local_err);
     } else {
         migration_ioc_register_yank(ioc);
-        ch = migration_ioc_process_incoming(ioc, &local_err);
+        ch = migration_channel_identify(mis, ioc, &local_err);
         if (!ch) {
             goto out;
         }
diff --git a/migration/channel.h b/migration/channel.h
index 0e189c4325..59d169e095 100644
--- a/migration/channel.h
+++ b/migration/channel.h
@@ -34,4 +34,8 @@ int migration_channel_read_peek(QIOChannel *ioc,
                                 const char *buf,
                                 const size_t buflen,
                                 Error **errp);
+
+bool migration_has_main_and_multifd_channels(void);
+bool migration_has_all_channels(void);
+
 #endif
diff --git a/migration/migration.c b/migration/migration.c
index 5f444958ef..540b419cda 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -927,8 +927,6 @@ out:
     migrate_incoming_unref_outgoing_state();
 }
 
-static bool migration_has_main_and_multifd_channels(void);
-
 bool migration_incoming_setup(QIOChannel *ioc, uint8_t channel, Error **errp)
 {
     MigrationIncomingState *mis = migration_incoming_get_current();
@@ -1018,100 +1016,6 @@ void migration_start_incoming(void)
     qemu_coroutine_enter(co);
 }
 
-static bool migration_has_main_and_multifd_channels(void)
-{
-    MigrationIncomingState *mis = migration_incoming_get_current();
-    if (!mis->from_src_file) {
-        /* main channel not established */
-        return false;
-    }
-
-    if (migrate_multifd() && !multifd_recv_all_channels_created()) {
-        return false;
-    }
-
-    /* main and all multifd channels are established */
-    return true;
-}
-
-uint8_t migration_ioc_process_incoming(QIOChannel *ioc, Error **errp)
-{
-    MigrationIncomingState *mis = migration_incoming_get_current();
-    uint8_t channel = CH_NONE;
-    uint32_t channel_magic = 0;
-    int ret = 0;
-
-    if (!migration_has_main_and_multifd_channels()) {
-        if (qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_READ_MSG_PEEK)) {
-            /*
-             * With multiple channels, it is possible that we receive channels
-             * out of order on destination side, causing incorrect mapping of
-             * source channels on destination side. Check channel MAGIC to
-             * decide type of channel. Please note this is best effort,
-             * postcopy preempt channel does not send any magic number so
-             * avoid it for postcopy live migration. Also tls live migration
-             * already does tls handshake while initializing main channel so
-             * with tls this issue is not possible.
-             */
-            ret = migration_channel_read_peek(ioc, (void *)&channel_magic,
-                                              sizeof(channel_magic), errp);
-            if (ret != 0) {
-                goto out;
-            }
-
-            channel_magic = be32_to_cpu(channel_magic);
-            if (channel_magic == QEMU_VM_FILE_MAGIC) {
-                channel = CH_MAIN;
-            } else if (channel_magic == MULTIFD_MAGIC) {
-                assert(migrate_multifd());
-                channel = CH_MULTIFD;
-            } else if (!mis->from_src_file &&
-                        mis->state == MIGRATION_STATUS_POSTCOPY_PAUSED) {
-                /* reconnect main channel for postcopy recovery */
-                channel = CH_MAIN;
-            } else {
-                error_setg(errp, "unknown channel magic: %u", channel_magic);
-            }
-        } else if (mis->from_src_file && migrate_multifd()) {
-            /*
-             * Non-peekable channels like tls/file are processed as
-             * multifd channels when multifd is enabled.
-             */
-            channel = CH_MULTIFD;
-        } else if (!mis->from_src_file) {
-            channel = CH_MAIN;
-        } else {
-            error_setg(errp, "non-peekable channel used without multifd");
-        }
-    } else {
-        assert(migrate_postcopy_preempt());
-        channel = CH_POSTCOPY;
-    }
-
-out:
-    return channel;
-}
-
-/**
- * @migration_has_all_channels: We have received all channels that we need
- *
- * Returns true when we have got connections to all the channels that
- * we need for migration.
- */
-bool migration_has_all_channels(void)
-{
-    if (!migration_has_main_and_multifd_channels()) {
-        return false;
-    }
-
-    MigrationIncomingState *mis = migration_incoming_get_current();
-    if (migrate_postcopy_preempt() && !mis->postcopy_qemufile_dst) {
-        return false;
-    }
-
-    return true;
-}
-
 int migrate_send_rp_switchover_ack(MigrationIncomingState *mis)
 {
     return migrate_send_rp_message(mis, MIG_RP_MSG_SWITCHOVER_ACK, 0, NULL);
diff --git a/migration/migration.h b/migration/migration.h
index b852464197..7689c97051 100644
--- a/migration/migration.h
+++ b/migration/migration.h
@@ -532,8 +532,6 @@ void migration_incoming_process(void);
 bool migration_incoming_setup(QIOChannel *ioc, uint8_t channel, Error **errp);
 void migration_outgoing_setup(QIOChannel *ioc);
 
-bool  migration_has_all_channels(void);
-
 void migration_connect_error_propagate(MigrationState *s, Error *error);
 void migrate_error_propagate(MigrationState *s, Error *error);
 bool migrate_has_error(MigrationState *s);
diff --git a/migration/rdma.c b/migration/rdma.c
index ef95ce440d..582e0651d4 100644
--- a/migration/rdma.c
+++ b/migration/rdma.c
@@ -18,6 +18,7 @@
 #include "channel.h"
 #include "qapi/error.h"
 #include "qemu/cutils.h"
+#include "channel.h"
 #include "exec/target_page.h"
 #include "rdma.h"
 #include "migration.h"
-- 
2.51.0
Re: [PATCH v2 18/25] migration: Move channel code to channel.c
Posted by Peter Xu 3 days, 14 hours ago
On Mon, Jan 05, 2026 at 04:06:35PM -0300, Fabiano Rosas wrote:
> Move the code responsible for the various channels connection into
> channel.c. This is all executed before the migration_thread and
> process_incoming_migration_co are running, so it helps the reasoning
> to have them out of migration.c.
> 
> migration_ioc_process_incoming becomes migration_channel_identify
> which is more in line with what the function does.
> 
> Signed-off-by: Fabiano Rosas <farosas@suse.de>

Reviewed-by: Peter Xu <peterx@redhat.com>

-- 
Peter Xu