[libvirt] [PATCH 2/2] libxl: handle external domain destroy
Jim Fehlig
jfehlig at suse.com
Mon Dec 10 21:30:37 UTC 2018
On 12/7/18 7:46 PM, Marek Marczykowski-Górecki wrote:
> If domain is killed with `xl destroy`, libvirt will not notice it and
> still report the domain as running. Also trying to destroy the domain
> through libvirt will fail. The only way to recover from such a situation
> is to restart libvirt daemon. The problem is that even though libxl
> report LIBXL_EVENT_TYPE_DOMAIN_DEATH, libvirt ignore it as all the
> domain cleanup is done in a function actually destroying the domain. If
> destroy is done outside of libvirt, there is no place where it would be
> handled.
>
> Fix this by doing domain cleanup in LIBXL_EVENT_TYPE_DOMAIN_DEATH too.
> To avoid doing it twice, add a ignoreDeathEvent flag
> libxlDomainObjPrivate, set when the domain death is triggered by libvirt
> itself.
>
> Signed-off-by: Marek Marczykowski-Górecki <marmarek at invisiblethingslab.com>
> ---
> src/libxl/libxl_domain.c | 71 ++++++++++++++++++++++++++++++++++++++--
> src/libxl/libxl_domain.h | 3 ++
> 2 files changed, 71 insertions(+), 3 deletions(-)
>
> diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c
> index 5fe3f44fbe..6d1e15b14c 100644
> --- a/src/libxl/libxl_domain.c
> +++ b/src/libxl/libxl_domain.c
> @@ -609,6 +609,54 @@ libxlDomainShutdownThread(void *opaque)
> virObjectUnref(cfg);
> }
>
> +static void
> +libxlDomainDeathThread(void *opaque)
> +{
> + struct libxlShutdownThreadInfo *shutdown_info = opaque;
> + virDomainObjPtr vm = NULL;
> + libxl_event *ev = shutdown_info->event;
> + libxlDriverPrivatePtr driver = shutdown_info->driver;
> + virObjectEventPtr dom_event = NULL;
> + libxlDriverConfigPtr cfg;
> + libxlDomainObjPrivatePtr priv;
> +
> + cfg = libxlDriverConfigGet(driver);
> +
> + vm = virDomainObjListFindByID(driver->domains, ev->domid);
> + if (!vm) {
> + /* vm->def->id already cleared, means the death was handled by the
> + * driver already */
> + goto cleanup;
> + }
> +
> + priv = vm->privateData;
> +
> + if (priv->ignoreDeathEvent) {
> + priv->ignoreDeathEvent = false;
> + goto cleanup;
> + }
> +
> + if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
> + goto cleanup;
> +
> + virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_DESTROYED);
> + dom_event = virDomainEventLifecycleNewFromObj(vm,
> + VIR_DOMAIN_EVENT_STOPPED,
> + VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
> + libxlDomainCleanup(driver, vm);
> + if (!vm->persistent)
> + virDomainObjListRemove(driver->domains, vm);
> + libxlDomainObjEndJob(driver, vm);
> +
> + cleanup:
> + virDomainObjEndAPI(&vm);
> + virObjectEventStateQueue(driver->domainEventState, dom_event);
> + libxl_event_free(cfg->ctx, ev);
> + VIR_FREE(shutdown_info);
> + virObjectUnref(cfg);
> +}
Thanks for adding death handling in a new function. libxlDomainShutdownThread()
is getting a bit unwieldy.
> +
> +
> /*
> * Handle previously registered domain event notification from libxenlight.
> */
> @@ -619,8 +667,10 @@ libxlDomainEventHandler(void *data, VIR_LIBXL_EVENT_CONST libxl_event *event)
> struct libxlShutdownThreadInfo *shutdown_info = NULL;
> virThread thread;
> libxlDriverConfigPtr cfg;
> + int ret = -1;
>
> - if (event->type != LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN) {
> + if (event->type != LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN &&
> + event->type != LIBXL_EVENT_TYPE_DOMAIN_DEATH) {
> VIR_INFO("Unhandled event type %d", event->type);
> goto error;
> }
> @@ -634,8 +684,14 @@ libxlDomainEventHandler(void *data, VIR_LIBXL_EVENT_CONST libxl_event *event)
>
> shutdown_info->driver = driver;
> shutdown_info->event = (libxl_event *)event;
> - if (virThreadCreate(&thread, false, libxlDomainShutdownThread,
> - shutdown_info) < 0) {
> + if (event->type == LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN)
> + ret = virThreadCreate(&thread, false, libxlDomainShutdownThread,
> + shutdown_info);
> + else if (event->type == LIBXL_EVENT_TYPE_DOMAIN_DEATH)
> + ret = virThreadCreate(&thread, false, libxlDomainDeathThread,
> + shutdown_info);
> +
> + if (ret < 0) {
> /*
> * Not much we can do on error here except log it.
> */
> @@ -751,14 +807,21 @@ libxlDomainDestroyInternal(libxlDriverPrivatePtr driver,
> virDomainObjPtr vm)
> {
> libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
> + libxlDomainObjPrivatePtr priv = vm->privateData;
> int ret = -1;
>
> + /* Ignore next LIBXL_EVENT_TYPE_DOMAIN_DEATH as the caller will handle
> + * domain death appropriately already (having more info, like the reason).
> + */
> + priv->ignoreDeathEvent = true;
> /* Unlock virDomainObj during destroy, which can take considerable
> * time on large memory domains.
> */
> virObjectUnlock(vm);
> ret = libxl_domain_destroy(cfg->ctx, vm->def->id, NULL);
> virObjectLock(vm);
> + if (ret)
> + priv->ignoreDeathEvent = false;
>
> virObjectUnref(cfg);
> return ret;
> @@ -811,6 +874,8 @@ libxlDomainCleanup(libxlDriverPrivatePtr driver,
> priv->deathW = NULL;
> }
>
> + priv->ignoreDeathEvent = false;
> +
> if (virAtomicIntDecAndTest(&driver->nactive) && driver->inhibitCallback)
> driver->inhibitCallback(false, driver->inhibitOpaque);
>
> diff --git a/src/libxl/libxl_domain.h b/src/libxl/libxl_domain.h
> index e193881450..993fd18f30 100644
> --- a/src/libxl/libxl_domain.h
> +++ b/src/libxl/libxl_domain.h
> @@ -65,6 +65,9 @@ struct _libxlDomainObjPrivate {
> /* console */
> virChrdevsPtr devs;
> libxl_evgen_domain_death *deathW;
> + /* the upcoming LIBXL_EVENT_TYPE_DOMAIN_DEATH is caused by libvirt and
> + * should not be handled separately */
I tweaked this comment a tiny bit by prefixing the sentence with "Flag to
indicate ".
> + bool ignoreDeathEvent;
> virThreadPtr migrationDstReceiveThr;
> unsigned short migrationPort;
> char *lockState;
>
Reviewed-by: Jim Fehlig <jfehlig at suse.com>
I've pushed both patches. Thanks!
Regards,
Jim
More information about the libvir-list
mailing list