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>
This commit is contained in:
Jim Fehlig 2021-11-24 11:36:55 -07:00
parent e4f7589a3e
commit b9a5faea49

View File

@ -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(libxlDriverPrivate *driver, virDomainObj *vm)
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, libxl_event *event)
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, libxl_event *event)
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;
thread_info = g_new0(struct libxlEventHandlerThreadInfo, 1);
/*
* 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);
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, libxl_event *event)
*/
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);
/*
* 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 death thread.
*/
libxlDomainHandleDeath(driver, vm);
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;
}
/*
* 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);