mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
libxl: handle domain shutdown events in a thread
Handling the domain shutdown event within the event handler seems a bit unfair to libxl's event machinery. Domain "shutdown" could take considerable time. E.g. if the shutdown reason is reboot, the domain must be reaped and then started again. Spawn a shutdown handler thread to do this work, allowing libxl's event machinery to go about its business. Signed-off-by: Jim Fehlig <jfehlig@suse.com>
This commit is contained in:
parent
eaa8d9b2c7
commit
03b3f8940a
@ -352,61 +352,107 @@ libxlVmReap(libxlDriverPrivatePtr driver,
|
|||||||
# define VIR_LIBXL_EVENT_CONST const
|
# define VIR_LIBXL_EVENT_CONST const
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct libxlShutdownThreadInfo
|
||||||
|
{
|
||||||
|
virDomainObjPtr vm;
|
||||||
|
libxl_event *event;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
libxlEventHandler(void *data, VIR_LIBXL_EVENT_CONST libxl_event *event)
|
libxlDomainShutdownThread(void *opaque)
|
||||||
{
|
{
|
||||||
libxlDriverPrivatePtr driver = libxl_driver;
|
libxlDriverPrivatePtr driver = libxl_driver;
|
||||||
libxlDomainObjPrivatePtr priv = ((virDomainObjPtr)data)->privateData;
|
struct libxlShutdownThreadInfo *shutdown_info = opaque;
|
||||||
virDomainObjPtr vm = NULL;
|
virDomainObjPtr vm = shutdown_info->vm;
|
||||||
|
libxlDomainObjPrivatePtr priv = vm->privateData;
|
||||||
|
libxl_event *ev = shutdown_info->event;
|
||||||
|
libxl_ctx *ctx = priv->ctx;
|
||||||
virObjectEventPtr dom_event = NULL;
|
virObjectEventPtr dom_event = NULL;
|
||||||
libxl_shutdown_reason xl_reason = event->u.domain_shutdown.shutdown_reason;
|
libxl_shutdown_reason xl_reason = ev->u.domain_shutdown.shutdown_reason;
|
||||||
|
virDomainShutoffReason reason;
|
||||||
|
|
||||||
if (event->type == LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN) {
|
virObjectLock(vm);
|
||||||
virDomainShutoffReason reason;
|
|
||||||
|
|
||||||
/*
|
switch (xl_reason) {
|
||||||
* Similar to the xl implementation, ignore SUSPEND. Any actions needed
|
case LIBXL_SHUTDOWN_REASON_POWEROFF:
|
||||||
* after calling libxl_domain_suspend() are handled by it's callers.
|
case LIBXL_SHUTDOWN_REASON_CRASH:
|
||||||
*/
|
if (xl_reason == LIBXL_SHUTDOWN_REASON_CRASH) {
|
||||||
if (xl_reason == LIBXL_SHUTDOWN_REASON_SUSPEND)
|
dom_event = virDomainEventLifecycleNewFromObj(vm,
|
||||||
goto cleanup;
|
VIR_DOMAIN_EVENT_STOPPED,
|
||||||
|
VIR_DOMAIN_EVENT_STOPPED_CRASHED);
|
||||||
vm = virDomainObjListFindByID(driver->domains, event->domid);
|
reason = VIR_DOMAIN_SHUTOFF_CRASHED;
|
||||||
if (!vm)
|
} else {
|
||||||
goto cleanup;
|
reason = VIR_DOMAIN_SHUTOFF_SHUTDOWN;
|
||||||
|
}
|
||||||
switch (xl_reason) {
|
libxlVmReap(driver, vm, reason);
|
||||||
case LIBXL_SHUTDOWN_REASON_POWEROFF:
|
if (!vm->persistent) {
|
||||||
case LIBXL_SHUTDOWN_REASON_CRASH:
|
virDomainObjListRemove(driver->domains, vm);
|
||||||
if (xl_reason == LIBXL_SHUTDOWN_REASON_CRASH) {
|
vm = NULL;
|
||||||
dom_event = virDomainEventLifecycleNewFromObj(vm,
|
}
|
||||||
VIR_DOMAIN_EVENT_STOPPED,
|
break;
|
||||||
VIR_DOMAIN_EVENT_STOPPED_CRASHED);
|
case LIBXL_SHUTDOWN_REASON_REBOOT:
|
||||||
reason = VIR_DOMAIN_SHUTOFF_CRASHED;
|
libxlVmReap(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
|
||||||
} else {
|
libxlVmStart(driver, vm, 0, -1);
|
||||||
reason = VIR_DOMAIN_SHUTOFF_SHUTDOWN;
|
break;
|
||||||
}
|
default:
|
||||||
libxlVmReap(driver, vm, reason);
|
VIR_INFO("Unhandled shutdown_reason %d", xl_reason);
|
||||||
if (!vm->persistent) {
|
break;
|
||||||
virDomainObjListRemove(driver->domains, vm);
|
|
||||||
vm = NULL;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case LIBXL_SHUTDOWN_REASON_REBOOT:
|
|
||||||
libxlVmReap(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
|
|
||||||
libxlVmStart(driver, vm, 0, -1);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
VIR_INFO("Unhandled shutdown_reason %d", xl_reason);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
|
||||||
if (vm)
|
if (vm)
|
||||||
virObjectUnlock(vm);
|
virObjectUnlock(vm);
|
||||||
if (dom_event)
|
if (dom_event)
|
||||||
libxlDomainEventQueue(driver, dom_event);
|
libxlDomainEventQueue(driver, dom_event);
|
||||||
|
libxl_event_free(ctx, ev);
|
||||||
|
VIR_FREE(shutdown_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
libxlEventHandler(void *data, VIR_LIBXL_EVENT_CONST libxl_event *event)
|
||||||
|
{
|
||||||
|
virDomainObjPtr vm = data;
|
||||||
|
libxlDomainObjPrivatePtr priv = vm->privateData;
|
||||||
|
libxl_shutdown_reason xl_reason = event->u.domain_shutdown.shutdown_reason;
|
||||||
|
struct libxlShutdownThreadInfo *shutdown_info;
|
||||||
|
virThread thread;
|
||||||
|
|
||||||
|
if (event->type != LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN) {
|
||||||
|
VIR_INFO("Unhandled event type %d", event->type);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Similar to the xl implementation, ignore SUSPEND. Any actions needed
|
||||||
|
* after calling libxl_domain_suspend() are handled by it's callers.
|
||||||
|
*/
|
||||||
|
if (xl_reason == LIBXL_SHUTDOWN_REASON_SUSPEND)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
shutdown_info->vm = data;
|
||||||
|
shutdown_info->event = (libxl_event *)event;
|
||||||
|
if (virThreadCreate(&thread, false, libxlDomainShutdownThread,
|
||||||
|
shutdown_info) < 0) {
|
||||||
|
/*
|
||||||
|
* Not much we can do on error here except log it.
|
||||||
|
*/
|
||||||
|
VIR_ERROR(_("Failed to create thread to handle domain shutdown"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* libxl_event freed in shutdown thread
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
|
||||||
|
error:
|
||||||
/* Cast away any const */
|
/* Cast away any const */
|
||||||
libxl_event_free(priv->ctx, (libxl_event *)event);
|
libxl_event_free(priv->ctx, (libxl_event *)event);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user