mirror of
https://github.com/qemu/qemu.git
synced 2026-02-04 02:24:51 +00:00
migration: Handle error in the early async paths
Simplify migration_channel_connect() and migration_connect() to not take an error as input. Move the error handling into the paths that generate the error. To achieve this, call migration_connect_error_propagate() from socket.c and tls.c, which are the async paths. For the sync paths, the handling is done as normal by returning all the way to qmp_migrate_finish(), except that now the sync paths don't pass the error forward into migration_connect() anymore. Reviewed-by: Peter Xu <peterx@redhat.com> Reviewed-by: Prasad Pandit <pjp@fedoraproject.org> Link: https://lore.kernel.org/qemu-devel/20260123141656.6765-13-farosas@suse.de Signed-off-by: Fabiano Rosas <farosas@suse.de>
This commit is contained in:
@@ -60,38 +60,35 @@ void migration_channel_process_incoming(QIOChannel *ioc)
|
||||
*
|
||||
* @s: Current migration state
|
||||
* @ioc: Channel to which we are connecting
|
||||
* @error: Error indicating failure to connect, free'd here
|
||||
*/
|
||||
void migration_channel_connect(MigrationState *s,
|
||||
QIOChannel *ioc,
|
||||
Error *error)
|
||||
void migration_channel_connect(MigrationState *s, QIOChannel *ioc)
|
||||
{
|
||||
trace_migration_set_outgoing_channel(
|
||||
ioc, object_get_typename(OBJECT(ioc)), error);
|
||||
trace_migration_set_outgoing_channel(ioc, object_get_typename(OBJECT(ioc)));
|
||||
|
||||
if (!error) {
|
||||
if (migrate_channel_requires_tls_upgrade(ioc)) {
|
||||
migration_tls_channel_connect(s, ioc, &error);
|
||||
if (migrate_channel_requires_tls_upgrade(ioc)) {
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (!error) {
|
||||
/* tls_channel_connect will call back to this
|
||||
* function after the TLS handshake,
|
||||
* so we mustn't call migration_connect until then
|
||||
*/
|
||||
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
QEMUFile *f = qemu_file_new_output(ioc);
|
||||
|
||||
migration_ioc_register_yank(ioc);
|
||||
|
||||
qemu_mutex_lock(&s->qemu_file_lock);
|
||||
s->to_dst_file = f;
|
||||
qemu_mutex_unlock(&s->qemu_file_lock);
|
||||
migration_tls_channel_connect(s, ioc, &local_err);
|
||||
if (local_err) {
|
||||
migration_connect_error_propagate(s, local_err);
|
||||
}
|
||||
|
||||
/*
|
||||
* async: the above will call back to this function after
|
||||
* the TLS handshake is successfully completed.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
migration_connect(s, error);
|
||||
|
||||
QEMUFile *f = qemu_file_new_output(ioc);
|
||||
|
||||
migration_ioc_register_yank(ioc);
|
||||
|
||||
qemu_mutex_lock(&s->qemu_file_lock);
|
||||
s->to_dst_file = f;
|
||||
qemu_mutex_unlock(&s->qemu_file_lock);
|
||||
|
||||
migration_connect(s);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -20,9 +20,7 @@
|
||||
|
||||
void migration_channel_process_incoming(QIOChannel *ioc);
|
||||
|
||||
void migration_channel_connect(MigrationState *s,
|
||||
QIOChannel *ioc,
|
||||
Error *error_in);
|
||||
void migration_channel_connect(MigrationState *s, QIOChannel *ioc);
|
||||
|
||||
int migration_channel_read_peek(QIOChannel *ioc,
|
||||
const char *buf,
|
||||
|
||||
@@ -55,7 +55,7 @@ void exec_start_outgoing_migration(MigrationState *s, strList *command,
|
||||
}
|
||||
|
||||
qio_channel_set_name(ioc, "migration-exec-outgoing");
|
||||
migration_channel_connect(s, ioc, NULL);
|
||||
migration_channel_connect(s, ioc);
|
||||
object_unref(OBJECT(ioc));
|
||||
}
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ void fd_start_outgoing_migration(MigrationState *s, const char *fdname, Error **
|
||||
}
|
||||
|
||||
qio_channel_set_name(ioc, "migration-fd-outgoing");
|
||||
migration_channel_connect(s, ioc, NULL);
|
||||
migration_channel_connect(s, ioc);
|
||||
object_unref(OBJECT(ioc));
|
||||
}
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ void file_start_outgoing_migration(MigrationState *s,
|
||||
return;
|
||||
}
|
||||
qio_channel_set_name(ioc, "migration-file-outgoing");
|
||||
migration_channel_connect(s, ioc, NULL);
|
||||
migration_channel_connect(s, ioc);
|
||||
}
|
||||
|
||||
static gboolean file_accept_incoming_migration(QIOChannel *ioc,
|
||||
|
||||
@@ -1569,7 +1569,7 @@ static void migrate_error_free(MigrationState *s)
|
||||
s->error = NULL;
|
||||
}
|
||||
|
||||
static void migration_connect_error_propagate(MigrationState *s, Error *error)
|
||||
void migration_connect_error_propagate(MigrationState *s, Error *error)
|
||||
{
|
||||
MigrationStatus current = s->state;
|
||||
MigrationStatus next = MIGRATION_STATUS_NONE;
|
||||
@@ -4020,7 +4020,7 @@ fail_setup:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void migration_connect(MigrationState *s, Error *error_in)
|
||||
void migration_connect(MigrationState *s)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
uint64_t rate_limit;
|
||||
@@ -4028,13 +4028,6 @@ void migration_connect(MigrationState *s, Error *error_in)
|
||||
int ret;
|
||||
|
||||
s->expected_downtime = migrate_downtime_limit();
|
||||
if (error_in) {
|
||||
migration_connect_error_propagate(s, error_in);
|
||||
if (s->error) {
|
||||
error_report_err(error_copy(s->error));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (resume) {
|
||||
/* This is a resumed migration */
|
||||
|
||||
@@ -533,10 +533,11 @@ void migration_incoming_process(void);
|
||||
|
||||
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);
|
||||
|
||||
void migration_connect(MigrationState *s, Error *error_in);
|
||||
void migration_connect(MigrationState *s);
|
||||
|
||||
int migration_call_notifiers(MigrationEventType type, Error **errp);
|
||||
|
||||
|
||||
@@ -3996,7 +3996,7 @@ void rdma_start_outgoing_migration(void *opaque,
|
||||
|
||||
s->to_dst_file = rdma_new_output(rdma);
|
||||
s->rdma_migration = true;
|
||||
migration_connect(s, NULL);
|
||||
migration_connect(s);
|
||||
return;
|
||||
return_path_err:
|
||||
qemu_rdma_cleanup(rdma);
|
||||
|
||||
@@ -59,24 +59,25 @@ static void socket_outgoing_migration(QIOTask *task,
|
||||
gpointer opaque)
|
||||
{
|
||||
struct SocketConnectData *data = opaque;
|
||||
QIOChannel *sioc = QIO_CHANNEL(qio_task_get_source(task));
|
||||
g_autoptr(QIOChannel) sioc = QIO_CHANNEL(qio_task_get_source(task));
|
||||
Error *err = NULL;
|
||||
|
||||
if (qio_task_propagate_error(task, &err)) {
|
||||
trace_migration_socket_outgoing_error(error_get_pretty(err));
|
||||
goto out;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
trace_migration_socket_outgoing_connected();
|
||||
|
||||
if (migrate_zero_copy_send() &&
|
||||
!qio_channel_has_feature(sioc, QIO_CHANNEL_FEATURE_WRITE_ZERO_COPY)) {
|
||||
error_setg(&err, "Zero copy send feature not detected in host kernel");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
out:
|
||||
migration_channel_connect(data->s, sioc, err);
|
||||
object_unref(OBJECT(sioc));
|
||||
trace_migration_socket_outgoing_connected();
|
||||
migration_channel_connect(data->s, sioc);
|
||||
return;
|
||||
fail:
|
||||
trace_migration_socket_outgoing_error(error_get_pretty(err));
|
||||
migration_connect_error_propagate(data->s, err);
|
||||
}
|
||||
|
||||
void socket_start_outgoing_migration(MigrationState *s,
|
||||
|
||||
@@ -104,16 +104,17 @@ static void migration_tls_outgoing_handshake(QIOTask *task,
|
||||
gpointer opaque)
|
||||
{
|
||||
MigrationState *s = opaque;
|
||||
QIOChannel *ioc = QIO_CHANNEL(qio_task_get_source(task));
|
||||
g_autoptr(QIOChannel) ioc = QIO_CHANNEL(qio_task_get_source(task));
|
||||
Error *err = NULL;
|
||||
|
||||
if (qio_task_propagate_error(task, &err)) {
|
||||
trace_migration_tls_outgoing_handshake_error(error_get_pretty(err));
|
||||
} else {
|
||||
trace_migration_tls_outgoing_handshake_complete();
|
||||
migration_connect_error_propagate(s, err);
|
||||
return;
|
||||
}
|
||||
migration_channel_connect(s, ioc, err);
|
||||
object_unref(OBJECT(ioc));
|
||||
|
||||
trace_migration_tls_outgoing_handshake_complete();
|
||||
migration_channel_connect(s, ioc);
|
||||
}
|
||||
|
||||
QIOChannelTLS *migration_tls_client_create(QIOChannel *ioc,
|
||||
@@ -129,8 +130,7 @@ QIOChannelTLS *migration_tls_client_create(QIOChannel *ioc,
|
||||
return qio_channel_tls_new_client(ioc, creds, migrate_tls_hostname(), errp);
|
||||
}
|
||||
|
||||
void migration_tls_channel_connect(MigrationState *s,
|
||||
QIOChannel *ioc,
|
||||
void migration_tls_channel_connect(MigrationState *s, QIOChannel *ioc,
|
||||
Error **errp)
|
||||
{
|
||||
QIOChannelTLS *tioc;
|
||||
|
||||
@@ -29,8 +29,7 @@ void migration_tls_channel_process_incoming(QIOChannel *ioc, Error **errp);
|
||||
QIOChannelTLS *migration_tls_client_create(QIOChannel *ioc,
|
||||
Error **errp);
|
||||
|
||||
void migration_tls_channel_connect(MigrationState *s,
|
||||
QIOChannel *ioc,
|
||||
void migration_tls_channel_connect(MigrationState *s, QIOChannel *ioc,
|
||||
Error **errp);
|
||||
void migration_tls_channel_end(QIOChannel *ioc, Error **errp);
|
||||
/* Whether the QIO channel requires further TLS handshake? */
|
||||
|
||||
@@ -204,7 +204,7 @@ migration_transferred_bytes(uint64_t qemu_file, uint64_t multifd, uint64_t rdma)
|
||||
|
||||
# channel.c
|
||||
migration_set_incoming_channel(void *ioc, const char *ioctype) "ioc=%p ioctype=%s"
|
||||
migration_set_outgoing_channel(void *ioc, const char *ioctype, void *err) "ioc=%p ioctype=%s err=%p"
|
||||
migration_set_outgoing_channel(void *ioc, const char *ioctype) "ioc=%p ioctype=%s"
|
||||
|
||||
# global_state.c
|
||||
migrate_state_too_big(void) ""
|
||||
|
||||
Reference in New Issue
Block a user