File b9a5faea-libxl-handle-death-thread.patch of Package libvirt.29527
commit b9a5faea49b7412e26d7389af4c32fc2b3ee80e5
Author: Jim Fehlig <jfehlig@suse.com>
Date: Wed Nov 24 11:36:55 2021 -0700
libxl: Handle domain death events in a thread
Similar to domain shutdown events, processing domain death events can be a
lengthy process and we don't want to block the event handler while the
operation completes. Move the death handling function to a thread.
Signed-off-by: Jim Fehlig <jfehlig@suse.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
Index: libvirt-6.0.0/src/libxl/libxl_domain.c
===================================================================
--- libvirt-6.0.0.orig/src/libxl/libxl_domain.c
+++ libvirt-6.0.0/src/libxl/libxl_domain.c
@@ -604,12 +604,17 @@ libxlDomainShutdownThread(void *opaque)
}
static void
-libxlDomainHandleDeath(libxlDriverPrivatePtr driver, virDomainObjPtr vm)
+libxlDomainDeathThread(void *opaque)
{
+ struct libxlEventHandlerThreadInfo *death_info = opaque;
+ virDomainObjPtr vm = death_info->vm;
+ libxl_event *ev = death_info->event;
+ libxlDriverPrivatePtr driver = death_info->driver;
virObjectEventPtr dom_event = NULL;
+ g_autoptr(libxlDriverConfig) cfg = libxlDriverConfigGet(driver);
if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
- return;
+ goto cleanup;
virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_DESTROYED);
dom_event = virDomainEventLifecycleNewFromObj(vm,
@@ -620,6 +625,11 @@ libxlDomainHandleDeath(libxlDriverPrivat
virDomainObjListRemove(driver->domains, vm);
libxlDomainObjEndJob(driver, vm);
virObjectEventStateQueue(driver->domainEventState, dom_event);
+
+ cleanup:
+ virDomainObjEndAPI(&vm);
+ libxl_event_free(cfg->ctx, ev);
+ VIR_FREE(death_info);
}
@@ -633,6 +643,8 @@ libxlDomainEventHandler(void *data, VIR_
libxl_shutdown_reason xl_reason = event->u.domain_shutdown.shutdown_reason;
virDomainObjPtr vm = NULL;
g_autoptr(libxlDriverConfig) cfg = NULL;
+ struct libxlEventHandlerThreadInfo *thread_info = NULL;
+ virThread thread;
VIR_DEBUG("Received libxl event '%d' for domid '%d'", event->type, event->domid);
@@ -655,30 +667,27 @@ libxlDomainEventHandler(void *data, VIR_
goto cleanup;
}
+ /*
+ * Start event-specific threads to handle shutdown and death.
+ * They are potentially lengthy operations and we don't want to be
+ * blocking this event handler while they are in progress.
+ */
if (event->type == LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN) {
- struct libxlEventHandlerThreadInfo *shutdown_info = NULL;
- virThread thread;
-
- /*
- * Start a thread to handle shutdown. We don't want to be tying up
- * libxl's event machinery by doing a potentially lengthy shutdown.
- */
- if (VIR_ALLOC(shutdown_info) < 0)
+ if (VIR_ALLOC(thread_info) < 0)
goto cleanup;
- shutdown_info->driver = driver;
- shutdown_info->vm = vm;
- shutdown_info->event = (libxl_event *)event;
+ thread_info->driver = driver;
+ thread_info->vm = vm;
+ thread_info->event = (libxl_event *)event;
/*
* Cleanup will be handled by the shutdown thread.
*/
if (virThreadCreate(&thread, false, libxlDomainShutdownThread,
- shutdown_info) < 0) {
+ thread_info) < 0) {
/*
* Not much we can do on error here except log it.
*/
VIR_ERROR(_("Failed to create thread to handle domain shutdown"));
- VIR_FREE(shutdown_info);
goto cleanup;
}
/*
@@ -687,15 +696,34 @@ libxlDomainEventHandler(void *data, VIR_
*/
return;
} else if (event->type == LIBXL_EVENT_TYPE_DOMAIN_DEATH) {
+ if (VIR_ALLOC(thread_info) < 0)
+ goto cleanup;
+
+ thread_info->driver = driver;
+ thread_info->vm = vm;
+ thread_info->event = (libxl_event *)event;
/*
- * On death the domain is cleaned up from Xen's perspective.
- * Cleanup on the libvirt side can be done synchronously.
+ * Cleanup will be handled by the shutdown thread.
*/
- libxlDomainHandleDeath(driver, vm);
+ if (virThreadCreate(&thread, false, libxlDomainDeathThread,
+ thread_info) < 0) {
+ /*
+ * Not much we can do on error here except log it.
+ */
+ VIR_ERROR(_("Failed to create thread to handle domain death"));
+ goto cleanup;
+ }
+ /*
+ * virDomainObjEndAPI is called in the death thread, where
+ * libxlEventHandlerThreadInfo and libxl_event are also freed.
+ */
+ return;
+
}
cleanup:
virDomainObjEndAPI(&vm);
+ VIR_FREE(thread_info);
cfg = libxlDriverConfigGet(driver);
/* Cast away any const */
libxl_event_free(cfg->ctx, (libxl_event *)event);