mirror of
https://github.com/qemu/qemu.git
synced 2026-02-04 05:35:39 +00:00
migration: Move channel code to channel.c
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. Reviewed-by: Peter Xu <peterx@redhat.com> Link: https://lore.kernel.org/qemu-devel/20260123141656.6765-19-farosas@suse.de Signed-off-by: Fabiano Rosas <farosas@suse.de>
This commit is contained in:
@@ -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 MigChannelType migration_channel_identify(MigrationIncomingState *mis,
|
||||
QIOChannel *ioc, Error **errp)
|
||||
{
|
||||
MigChannelType 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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -926,8 +926,6 @@ out:
|
||||
migrate_incoming_unref_outgoing_state();
|
||||
}
|
||||
|
||||
static bool migration_has_main_and_multifd_channels(void);
|
||||
|
||||
/*
|
||||
* Returns whether all the necessary channels to proceed with the
|
||||
* incoming migration have been established without error.
|
||||
@@ -1021,100 +1019,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;
|
||||
}
|
||||
|
||||
MigChannelType migration_ioc_process_incoming(QIOChannel *ioc, Error **errp)
|
||||
{
|
||||
MigrationIncomingState *mis = migration_incoming_get_current();
|
||||
MigChannelType 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);
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include "postcopy-ram.h"
|
||||
#include "system/runstate.h"
|
||||
#include "migration/misc.h"
|
||||
#include "channel.h"
|
||||
|
||||
#define MIGRATION_THREAD_SNAPSHOT "mig/snapshot"
|
||||
#define MIGRATION_THREAD_DIRTY_RATE "mig/dirtyrate"
|
||||
@@ -528,13 +527,10 @@ struct MigrationState {
|
||||
void migrate_set_state(MigrationStatus *state, MigrationStatus old_state,
|
||||
MigrationStatus new_state);
|
||||
|
||||
MigChannelType migration_ioc_process_incoming(QIOChannel *ioc, Error **errp);
|
||||
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);
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user