@@ -1617,14 +1617,62 @@ void postcopy_preempt_new_channel(MigrationIncomingState *mis, QEMUFile *file)
trace_postcopy_preempt_new_channel();
}
+typedef struct {
+ unsigned int ref;
+ MigrationState *s;
+} PostcopyPChannelConnectData;
+
+static PostcopyPChannelConnectData *pcopy_preempt_connect_data_new(MigrationState *s)
+{
+ PostcopyPChannelConnectData *data;
+
+ data = g_malloc0(sizeof(*data));
+ data->ref = 1;
+ data->s = s;
+
+ return data;
+}
+
+static void pcopy_preempt_connect_data_free(PostcopyPChannelConnectData *data)
+{
+ g_free(data);
+}
+
+static PostcopyPChannelConnectData *
+pcopy_preempt_connect_data_ref(PostcopyPChannelConnectData *data)
+{
+ unsigned int ref_old;
+
+ ref_old = qatomic_fetch_inc(&data->ref);
+ assert(ref_old < UINT_MAX);
+
+ return data;
+}
+
+static void pcopy_preempt_connect_data_unref(gpointer opaque)
+{
+ PostcopyPChannelConnectData *data = opaque;
+ unsigned int ref_old;
+
+ ref_old = qatomic_fetch_dec(&data->ref);
+ assert(ref_old > 0);
+ if (ref_old == 1) {
+ pcopy_preempt_connect_data_free(data);
+ }
+}
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(PostcopyPChannelConnectData, pcopy_preempt_connect_data_unref)
+
/*
* Setup the postcopy preempt channel with the IOC. If ERROR is specified,
* setup the error instead. This helper will free the ERROR if specified.
*/
static void
-postcopy_preempt_send_channel_done(MigrationState *s,
+postcopy_preempt_send_channel_done(PostcopyPChannelConnectData *data,
QIOChannel *ioc, Error *local_err)
{
+ MigrationState *s = data->s;
+
if (local_err) {
migrate_set_error(s, local_err);
error_free(local_err);
@@ -1645,18 +1693,19 @@ static void
postcopy_preempt_tls_handshake(QIOTask *task, gpointer opaque)
{
g_autoptr(QIOChannel) ioc = QIO_CHANNEL(qio_task_get_source(task));
- MigrationState *s = opaque;
+ PostcopyPChannelConnectData *data = opaque;
Error *local_err = NULL;
qio_task_propagate_error(task, &local_err);
- postcopy_preempt_send_channel_done(s, ioc, local_err);
+ postcopy_preempt_send_channel_done(data, ioc, local_err);
}
static void
postcopy_preempt_send_channel_new(QIOTask *task, gpointer opaque)
{
g_autoptr(QIOChannel) ioc = QIO_CHANNEL(qio_task_get_source(task));
- MigrationState *s = opaque;
+ PostcopyPChannelConnectData *data = opaque;
+ MigrationState *s = data->s;
QIOChannelTLS *tioc;
Error *local_err = NULL;
@@ -1672,14 +1721,15 @@ postcopy_preempt_send_channel_new(QIOTask *task, gpointer opaque)
trace_postcopy_preempt_tls_handshake();
qio_channel_set_name(QIO_CHANNEL(tioc), "migration-tls-preempt");
qio_channel_tls_handshake(tioc, postcopy_preempt_tls_handshake,
- s, NULL, NULL);
+ pcopy_preempt_connect_data_ref(data),
+ pcopy_preempt_connect_data_unref, NULL);
/* Setup the channel until TLS handshake finished */
return;
}
out:
/* This handles both good and error cases */
- postcopy_preempt_send_channel_done(s, ioc, local_err);
+ postcopy_preempt_send_channel_done(data, ioc, local_err);
}
/*
@@ -1714,8 +1764,12 @@ int postcopy_preempt_establish_channel(MigrationState *s)
void postcopy_preempt_setup(MigrationState *s)
{
+ PostcopyPChannelConnectData *data;
+
+ data = pcopy_preempt_connect_data_new(s);
/* Kick an async task to connect */
- socket_send_channel_create(postcopy_preempt_send_channel_new, s, NULL);
+ socket_send_channel_create(postcopy_preempt_send_channel_new,
+ data, pcopy_preempt_connect_data_unref);
}
static void postcopy_pause_ram_fast_load(MigrationIncomingState *mis)