aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Xu <peterx@redhat.com>2024-02-22 17:52:57 +0800
committerPeter Xu <peterx@redhat.com>2024-02-28 11:31:28 +0800
commit9221e3c6a237da90ac296adfeb6e99ea9babfc20 (patch)
tree6c9ea5494aa43f8ac8771887106708aaa3799922
parentd13f0026c7a625a5a34a5dea4095a4d9cfa04652 (diff)
downloadqemu-9221e3c6a237da90ac296adfeb6e99ea9babfc20.zip
qemu-9221e3c6a237da90ac296adfeb6e99ea9babfc20.tar.gz
qemu-9221e3c6a237da90ac296adfeb6e99ea9babfc20.tar.bz2
migration/multifd: Cleanup TLS iochannel referencing
Commit a1af605bd5 ("migration/multifd: fix hangup with TLS-Multifd due to blocking handshake") introduced a thread for TLS channels, which will resolve the issue on blocking the main thread. However in the same commit p->c is slightly abused just to be able to pass over the pointer "p" into the thread. That's the major reason we'll need to conditionally free the io channel in the fault paths. To clean it up, using a separate structure to pass over both "p" and "tioc" in the tls handshake thread. Then we can make it a rule that p->c will never be set until the channel is completely setup. With that, we can drop the tricky conditional unref of the io channel in the error path. Reviewed-by: Fabiano Rosas <farosas@suse.de> Link: https://lore.kernel.org/r/20240222095301.171137-2-peterx@redhat.com Signed-off-by: Peter Xu <peterx@redhat.com>
-rw-r--r--migration/multifd.c37
1 files changed, 23 insertions, 14 deletions
diff --git a/migration/multifd.c b/migration/multifd.c
index 43f0820..84a6b9e 100644
--- a/migration/multifd.c
+++ b/migration/multifd.c
@@ -891,16 +891,22 @@ out:
static void multifd_new_send_channel_async(QIOTask *task, gpointer opaque);
+typedef struct {
+ MultiFDSendParams *p;
+ QIOChannelTLS *tioc;
+} MultiFDTLSThreadArgs;
+
static void *multifd_tls_handshake_thread(void *opaque)
{
- MultiFDSendParams *p = opaque;
- QIOChannelTLS *tioc = QIO_CHANNEL_TLS(p->c);
+ MultiFDTLSThreadArgs *args = opaque;
- qio_channel_tls_handshake(tioc,
+ qio_channel_tls_handshake(args->tioc,
multifd_new_send_channel_async,
- p,
+ args->p,
NULL,
NULL);
+ g_free(args);
+
return NULL;
}
@@ -910,6 +916,7 @@ static bool multifd_tls_channel_connect(MultiFDSendParams *p,
{
MigrationState *s = migrate_get_current();
const char *hostname = s->hostname;
+ MultiFDTLSThreadArgs *args;
QIOChannelTLS *tioc;
tioc = migration_tls_client_create(ioc, hostname, errp);
@@ -924,11 +931,14 @@ static bool multifd_tls_channel_connect(MultiFDSendParams *p,
object_unref(OBJECT(ioc));
trace_multifd_tls_outgoing_handshake_start(ioc, tioc, hostname);
qio_channel_set_name(QIO_CHANNEL(tioc), "multifd-tls-outgoing");
- p->c = QIO_CHANNEL(tioc);
+
+ args = g_new0(MultiFDTLSThreadArgs, 1);
+ args->tioc = tioc;
+ args->p = p;
p->tls_thread_created = true;
qemu_thread_create(&p->tls_thread, "multifd-tls-handshake-worker",
- multifd_tls_handshake_thread, p,
+ multifd_tls_handshake_thread, args,
QEMU_THREAD_JOINABLE);
return true;
}
@@ -941,6 +951,7 @@ static bool multifd_channel_connect(MultiFDSendParams *p,
migration_ioc_register_yank(ioc);
p->registered_yank = true;
+ /* Setup p->c only if the channel is completely setup */
p->c = ioc;
p->thread_created = true;
@@ -994,14 +1005,12 @@ out:
trace_multifd_new_send_channel_async_error(p->id, local_err);
multifd_send_set_error(local_err);
- if (!p->c) {
- /*
- * If no channel has been created, drop the initial
- * reference. Otherwise cleanup happens at
- * multifd_send_channel_destroy()
- */
- object_unref(OBJECT(ioc));
- }
+ /*
+ * For error cases (TLS or non-TLS), IO channel is always freed here
+ * rather than when cleanup multifd: since p->c is not set, multifd
+ * cleanup code doesn't even know its existence.
+ */
+ object_unref(OBJECT(ioc));
error_free(local_err);
}