@@ -62,7 +62,10 @@ bool file_send_channel_create(gpointer opaque, Error **errp)
goto out;
}
- multifd_channel_connect(opaque, QIO_CHANNEL(ioc));
+ ret = multifd_channel_connect(opaque, QIO_CHANNEL(ioc), errp);
+ if (!ret) {
+ object_unref(OBJECT(ioc));
+ }
out:
/*
@@ -1010,34 +1010,76 @@ out:
return NULL;
}
-static void multifd_new_send_channel_async(QIOTask *task, gpointer opaque);
-
-typedef struct {
+struct MFDSendChannelConnectData {
+ unsigned int ref;
MultiFDSendParams *p;
QIOChannelTLS *tioc;
-} MultiFDTLSThreadArgs;
+};
+
+static MFDSendChannelConnectData *mfd_send_channel_connect_data_new(MultiFDSendParams *p)
+{
+ MFDSendChannelConnectData *data;
+
+ data = g_malloc0(sizeof(*data));
+ data->ref = 1;
+ data->p = p;
+
+ return data;
+}
+
+static void mfd_send_channel_connect_data_free(MFDSendChannelConnectData *data)
+{
+ g_free(data);
+}
+
+static MFDSendChannelConnectData *
+mfd_send_channel_connect_data_ref(MFDSendChannelConnectData *data)
+{
+ unsigned int ref_old;
+
+ ref_old = qatomic_fetch_inc(&data->ref);
+ assert(ref_old < UINT_MAX);
+
+ return data;
+}
+
+static void mfd_send_channel_connect_data_unref(gpointer opaque)
+{
+ MFDSendChannelConnectData *data = opaque;
+ unsigned int ref_old;
+
+ ref_old = qatomic_fetch_dec(&data->ref);
+ assert(ref_old > 0);
+ if (ref_old == 1) {
+ mfd_send_channel_connect_data_free(data);
+ }
+}
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(MFDSendChannelConnectData, mfd_send_channel_connect_data_unref)
+
+static void multifd_new_send_channel_async(QIOTask *task, gpointer opaque);
static void *multifd_tls_handshake_thread(void *opaque)
{
- MultiFDTLSThreadArgs *args = opaque;
+ g_autoptr(MFDSendChannelConnectData) data = opaque;
+ QIOChannelTLS *tioc = data->tioc;
- qio_channel_tls_handshake(args->tioc,
+ qio_channel_tls_handshake(tioc,
multifd_new_send_channel_async,
- args->p,
- NULL,
+ g_steal_pointer(&data),
+ mfd_send_channel_connect_data_unref,
NULL);
- g_free(args);
return NULL;
}
-static bool multifd_tls_channel_connect(MultiFDSendParams *p,
+static bool multifd_tls_channel_connect(MFDSendChannelConnectData *data,
QIOChannel *ioc,
Error **errp)
{
+ MultiFDSendParams *p = data->p;
MigrationState *s = migrate_get_current();
const char *hostname = s->hostname;
- MultiFDTLSThreadArgs *args;
QIOChannelTLS *tioc;
tioc = migration_tls_client_create(ioc, hostname, errp);
@@ -1053,19 +1095,21 @@ static bool multifd_tls_channel_connect(MultiFDSendParams *p,
trace_multifd_tls_outgoing_handshake_start(ioc, tioc, hostname);
qio_channel_set_name(QIO_CHANNEL(tioc), "multifd-tls-outgoing");
- args = g_new0(MultiFDTLSThreadArgs, 1);
- args->tioc = tioc;
- args->p = p;
+ data->tioc = tioc;
p->tls_thread_created = true;
qemu_thread_create(&p->tls_thread, "multifd-tls-handshake-worker",
- multifd_tls_handshake_thread, args,
+ multifd_tls_handshake_thread,
+ mfd_send_channel_connect_data_ref(data),
QEMU_THREAD_JOINABLE);
return true;
}
-void multifd_channel_connect(MultiFDSendParams *p, QIOChannel *ioc)
+bool multifd_channel_connect(MFDSendChannelConnectData *data, QIOChannel *ioc,
+ Error **errp)
{
+ MultiFDSendParams *p = data->p;
+
qio_channel_set_delay(ioc, false);
migration_ioc_register_yank(ioc);
@@ -1075,6 +1119,8 @@ void multifd_channel_connect(MultiFDSendParams *p, QIOChannel *ioc)
p->thread_created = true;
qemu_thread_create(&p->thread, p->name, multifd_send_thread, p,
QEMU_THREAD_JOINABLE);
+
+ return true;
}
/*
@@ -1085,7 +1131,8 @@ void multifd_channel_connect(MultiFDSendParams *p, QIOChannel *ioc)
*/
static void multifd_new_send_channel_async(QIOTask *task, gpointer opaque)
{
- MultiFDSendParams *p = opaque;
+ MFDSendChannelConnectData *data = opaque;
+ MultiFDSendParams *p = data->p;
QIOChannel *ioc = QIO_CHANNEL(qio_task_get_source(task));
Error *local_err = NULL;
bool ret;
@@ -1101,13 +1148,12 @@ static void multifd_new_send_channel_async(QIOTask *task, gpointer opaque)
migrate_get_current()->hostname);
if (migrate_channel_requires_tls_upgrade(ioc)) {
- ret = multifd_tls_channel_connect(p, ioc, &local_err);
+ ret = multifd_tls_channel_connect(data, ioc, &local_err);
if (ret) {
return;
}
} else {
- multifd_channel_connect(p, ioc);
- ret = true;
+ ret = multifd_channel_connect(data, ioc, &local_err);
}
out:
@@ -1134,11 +1180,16 @@ out:
static bool multifd_new_send_channel_create(MultiFDSendParams *p, Error **errp)
{
+ g_autoptr(MFDSendChannelConnectData) data = NULL;
+
+ data = mfd_send_channel_connect_data_new(p);
+
if (!multifd_use_packets()) {
- return file_send_channel_create(p, errp);
+ return file_send_channel_create(data, errp);
}
- socket_send_channel_create(multifd_new_send_channel_async, p, NULL);
+ socket_send_channel_create(multifd_new_send_channel_async, g_steal_pointer(&data),
+ mfd_send_channel_connect_data_unref);
return true;
}
@@ -250,6 +250,8 @@ static inline void multifd_send_prepare_header(MultiFDSendParams *p)
p->iovs_num++;
}
-void multifd_channel_connect(MultiFDSendParams *p, QIOChannel *ioc);
+struct MFDSendChannelConnectData;
+typedef struct MFDSendChannelConnectData MFDSendChannelConnectData;
+bool multifd_channel_connect(MFDSendChannelConnectData *data, QIOChannel *ioc, Error **errp);
#endif