forked from pool/libvirt
141 lines
5.4 KiB
Diff
141 lines
5.4 KiB
Diff
|
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-7.10.0/src/libxl/libxl_domain.c
|
||
|
===================================================================
|
||
|
--- libvirt-7.10.0.orig/src/libxl/libxl_domain.c
|
||
|
+++ libvirt-7.10.0/src/libxl/libxl_domain.c
|
||
|
@@ -613,12 +613,17 @@ libxlDomainShutdownThread(void *opaque)
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
-libxlDomainHandleDeath(libxlDriverPrivate *driver, virDomainObj *vm)
|
||
|
+libxlDomainDeathThread(void *opaque)
|
||
|
{
|
||
|
+ struct libxlEventHandlerThreadInfo *death_info = opaque;
|
||
|
+ virDomainObj *vm = death_info->vm;
|
||
|
+ libxl_event *ev = death_info->event;
|
||
|
+ libxlDriverPrivate *driver = death_info->driver;
|
||
|
virObjectEvent *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,
|
||
|
@@ -629,6 +634,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);
|
||
|
}
|
||
|
|
||
|
|
||
|
@@ -642,6 +652,9 @@ libxlDomainEventHandler(void *data, libx
|
||
|
libxl_shutdown_reason xl_reason = event->u.domain_shutdown.shutdown_reason;
|
||
|
virDomainObj *vm = NULL;
|
||
|
g_autoptr(libxlDriverConfig) cfg = NULL;
|
||
|
+ struct libxlEventHandlerThreadInfo *thread_info = NULL;
|
||
|
+ virThread thread;
|
||
|
+ g_autofree char *thread_name = NULL;
|
||
|
|
||
|
VIR_DEBUG("Received libxl event '%d' for domid '%d'", event->type, event->domid);
|
||
|
|
||
|
@@ -664,31 +677,27 @@ libxlDomainEventHandler(void *data, libx
|
||
|
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;
|
||
|
- g_autofree char *name = NULL;
|
||
|
-
|
||
|
- /*
|
||
|
- * Start a thread to handle shutdown. We don't want to be tying up
|
||
|
- * libxl's event machinery by doing a potentially lengthy shutdown.
|
||
|
- */
|
||
|
- shutdown_info = g_new0(struct libxlEventHandlerThreadInfo, 1);
|
||
|
+ thread_info = g_new0(struct libxlEventHandlerThreadInfo, 1);
|
||
|
|
||
|
- shutdown_info->driver = driver;
|
||
|
- shutdown_info->vm = vm;
|
||
|
- shutdown_info->event = (libxl_event *)event;
|
||
|
- name = g_strdup_printf("shutdown-event-%d", event->domid);
|
||
|
+ thread_info->driver = driver;
|
||
|
+ thread_info->vm = vm;
|
||
|
+ thread_info->event = (libxl_event *)event;
|
||
|
+ thread_name = g_strdup_printf("shutdown-event-%d", event->domid);
|
||
|
/*
|
||
|
* Cleanup will be handled by the shutdown thread.
|
||
|
*/
|
||
|
if (virThreadCreateFull(&thread, false, libxlDomainShutdownThread,
|
||
|
- name, false, shutdown_info) < 0) {
|
||
|
+ thread_name, false, 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;
|
||
|
}
|
||
|
/*
|
||
|
@@ -697,15 +706,33 @@ libxlDomainEventHandler(void *data, libx
|
||
|
*/
|
||
|
return;
|
||
|
} else if (event->type == LIBXL_EVENT_TYPE_DOMAIN_DEATH) {
|
||
|
+ thread_info = g_new0(struct libxlEventHandlerThreadInfo, 1);
|
||
|
+
|
||
|
+ thread_info->driver = driver;
|
||
|
+ thread_info->vm = vm;
|
||
|
+ thread_info->event = (libxl_event *)event;
|
||
|
+ thread_name = g_strdup_printf("death-event-%d", event->domid);
|
||
|
+ /*
|
||
|
+ * Cleanup will be handled by the death thread.
|
||
|
+ */
|
||
|
+ if (virThreadCreateFull(&thread, false, libxlDomainDeathThread,
|
||
|
+ thread_name, false, 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;
|
||
|
+ }
|
||
|
/*
|
||
|
- * On death the domain is cleaned up from Xen's perspective.
|
||
|
- * Cleanup on the libvirt side can be done synchronously.
|
||
|
+ * virDomainObjEndAPI is called in the death thread, where
|
||
|
+ * libxlEventHandlerThreadInfo and libxl_event are also freed.
|
||
|
*/
|
||
|
- libxlDomainHandleDeath(driver, vm);
|
||
|
+ return;
|
||
|
}
|
||
|
|
||
|
cleanup:
|
||
|
virDomainObjEndAPI(&vm);
|
||
|
+ VIR_FREE(thread_info);
|
||
|
cfg = libxlDriverConfigGet(driver);
|
||
|
/* Cast away any const */
|
||
|
libxl_event_free(cfg->ctx, (libxl_event *)event);
|