diff --git a/87a9d3a6-libxl-fix-domain-shutdown.patch b/87a9d3a6-libxl-fix-domain-shutdown.patch new file mode 100644 index 0000000..afc517d --- /dev/null +++ b/87a9d3a6-libxl-fix-domain-shutdown.patch @@ -0,0 +1,219 @@ +commit 87a9d3a6b01baebdca33d95ad0e79781b6a46ca8 +Author: Jim Fehlig +Date: Fri Feb 19 16:29:10 2021 -0700 + + libxl: Fix domain shutdown + + Commit fa30ee04a2 caused a regression in normal domain shutown. + Initiating a shutdown from within the domain or via 'virsh shutdown' + does cause the guest OS running in the domain to shutdown, but libvirt + never reaps the domain so it is always shown in a running state until + calling 'virsh destroy'. + + The shutdown thread is also an internal user of the driver shutdown + machinery and eventually calls libxlDomainDestroyInternal where + the ignoreDeathEvent inhibitor is set, but running in a thread + introduces the possibility of racing with the death event from + libxl. This can be prevented by setting ignoreDeathEvent before + running the shutdown thread. + + An additional improvement is to handle the destroy event synchronously + instead of spawning a thread. The time consuming aspects of destroying + a domain have been completed when the destroy event is delivered. + + Signed-off-by: Jim Fehlig + Reviewed-by: Michal Privoznik + +Index: libvirt-7.0.0/src/libxl/libxl_domain.c +=================================================================== +--- libvirt-7.0.0.orig/src/libxl/libxl_domain.c ++++ libvirt-7.0.0/src/libxl/libxl_domain.c +@@ -476,6 +476,7 @@ libxlDomainShutdownHandleRestart(libxlDr + struct libxlShutdownThreadInfo + { + libxlDriverPrivatePtr driver; ++ virDomainObjPtr vm; + libxl_event *event; + }; + +@@ -484,7 +485,7 @@ static void + libxlDomainShutdownThread(void *opaque) + { + struct libxlShutdownThreadInfo *shutdown_info = opaque; +- virDomainObjPtr vm = NULL; ++ virDomainObjPtr vm = shutdown_info->vm; + libxl_event *ev = shutdown_info->event; + libxlDriverPrivatePtr driver = shutdown_info->driver; + virObjectEventPtr dom_event = NULL; +@@ -494,12 +495,6 @@ libxlDomainShutdownThread(void *opaque) + + libxl_domain_config_init(&d_config); + +- vm = virDomainObjListFindByID(driver->domains, ev->domid); +- if (!vm) { +- VIR_INFO("Received event for unknown domain ID %d", ev->domid); +- goto cleanup; +- } +- + if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) + goto cleanup; + +@@ -616,32 +611,18 @@ libxlDomainShutdownThread(void *opaque) + } + + static void +-libxlDomainDeathThread(void *opaque) ++libxlDomainHandleDeath(libxlDriverPrivatePtr driver, virDomainObjPtr vm) + { +- struct libxlShutdownThreadInfo *shutdown_info = opaque; +- virDomainObjPtr vm = NULL; +- libxl_event *ev = shutdown_info->event; +- libxlDriverPrivatePtr driver = shutdown_info->driver; + virObjectEventPtr dom_event = NULL; +- g_autoptr(libxlDriverConfig) cfg = libxlDriverConfigGet(driver); +- libxlDomainObjPrivatePtr priv; +- +- 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; ++ libxlDomainObjPrivatePtr priv = vm->privateData; + + if (priv->ignoreDeathEvent) { + priv->ignoreDeathEvent = false; +- goto cleanup; ++ return; + } + + if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) +- goto cleanup; ++ return; + + virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_DESTROYED); + dom_event = virDomainEventLifecycleNewFromObj(vm, +@@ -651,12 +632,7 @@ libxlDomainDeathThread(void *opaque) + 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); + } + + +@@ -668,16 +644,13 @@ libxlDomainEventHandler(void *data, VIR_ + { + libxlDriverPrivatePtr driver = data; + libxl_shutdown_reason xl_reason = event->u.domain_shutdown.shutdown_reason; +- struct libxlShutdownThreadInfo *shutdown_info = NULL; +- virThread thread; ++ virDomainObjPtr vm = NULL; + g_autoptr(libxlDriverConfig) cfg = NULL; +- int ret = -1; +- g_autofree char *name = NULL; + + 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; ++ goto cleanup; + } + + /* +@@ -685,42 +658,63 @@ libxlDomainEventHandler(void *data, VIR_ + * after calling libxl_domain_suspend() are handled by its callers. + */ + if (xl_reason == LIBXL_SHUTDOWN_REASON_SUSPEND) +- goto error; ++ goto cleanup; + +- /* +- * 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 libxlShutdownThreadInfo, 1); ++ vm = virDomainObjListFindByID(driver->domains, event->domid); ++ if (!vm) { ++ /* Nothing to do if we can't find the virDomainObj */ ++ goto cleanup; ++ } + +- shutdown_info->driver = driver; +- shutdown_info->event = (libxl_event *)event; +- name = g_strdup_printf("ev-%d", event->domid); +- if (event->type == LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN) +- ret = virThreadCreateFull(&thread, false, libxlDomainShutdownThread, +- name, false, shutdown_info); +- else if (event->type == LIBXL_EVENT_TYPE_DOMAIN_DEATH) +- ret = virThreadCreateFull(&thread, false, libxlDomainDeathThread, +- name, false, shutdown_info); ++ if (event->type == LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN) { ++ libxlDomainObjPrivatePtr priv = vm->privateData; ++ struct libxlShutdownThreadInfo *shutdown_info = NULL; ++ virThread thread; ++ g_autofree char *name = NULL; + +- if (ret < 0) { + /* +- * Not much we can do on error here except log it. ++ * Start a thread to handle shutdown. We don't want to be tying up ++ * libxl's event machinery by doing a potentially lengthy shutdown. + */ +- VIR_ERROR(_("Failed to create thread to handle domain shutdown")); +- goto error; +- } ++ shutdown_info = g_new0(struct libxlShutdownThreadInfo, 1); + +- /* +- * libxlShutdownThreadInfo and libxl_event are freed in shutdown thread +- */ +- return; ++ shutdown_info->driver = driver; ++ shutdown_info->vm = vm; ++ shutdown_info->event = (libxl_event *)event; ++ name = g_strdup_printf("ev-%d", event->domid); ++ /* ++ * Cleanup will be handled by the shutdown thread. ++ * Ignore the forthcoming death event from libxl ++ */ ++ priv->ignoreDeathEvent = true; ++ if (virThreadCreateFull(&thread, false, libxlDomainShutdownThread, ++ name, false, shutdown_info) < 0) { ++ priv->ignoreDeathEvent = false; ++ /* ++ * 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; ++ } ++ /* ++ * virDomainObjEndAPI is called in the shutdown thread, where ++ * libxlShutdownThreadInfo and libxl_event are also freed. ++ */ ++ return; ++ } else if (event->type == LIBXL_EVENT_TYPE_DOMAIN_DEATH) { ++ /* ++ * On death the domain is cleaned up from Xen's perspective. ++ * Cleanup on the libvirt side can be done synchronously. ++ */ ++ libxlDomainHandleDeath(driver, vm); ++ } + +- error: ++ cleanup: ++ virDomainObjEndAPI(&vm); + cfg = libxlDriverConfigGet(driver); + /* Cast away any const */ + libxl_event_free(cfg->ctx, (libxl_event *)event); +- VIR_FREE(shutdown_info); + } + + char * diff --git a/libvirt.changes b/libvirt.changes index 8fdf456..2d0cb4b 100644 --- a/libvirt.changes +++ b/libvirt.changes @@ -1,3 +1,17 @@ +------------------------------------------------------------------- +Mon Feb 22 18:07:47 UTC 2021 - James Fehlig + +- libxl: Fix domain shutdown + 87a9d3a6-libxl-fix-domain-shutdown.patch + bsc#1182515 + +------------------------------------------------------------------- +Sat Feb 20 00:51:09 UTC 2021 - James Fehlig + +- Remove old initscript patching of libvirt-guests.sh + Modified suse-libvirt-guests-service.patch + boo#1182494 + ------------------------------------------------------------------- Wed Feb 17 15:11:25 UTC 2021 - James Fehlig diff --git a/libvirt.spec b/libvirt.spec index c971430..8344499 100644 --- a/libvirt.spec +++ b/libvirt.spec @@ -299,6 +299,7 @@ Patch4: 8a4b8996-conf-move-virDomainCheckVirtioOptions.patch Patch5: c05f0066-conf-drop-empty-virDomainNetDefPostParse.patch Patch6: 19d4e467-conf-improve-virDomainVirtioOptionsCheckABIStability.patch Patch7: bd112c9e-qemu-virtio-options-vsock.patch +Patch8: 87a9d3a6-libxl-fix-domain-shutdown.patch # Patches pending upstream review Patch100: libxl-dom-reset.patch Patch101: network-don-t-use-dhcp-authoritative-on-static-netwo.patch diff --git a/suse-bump-xen-version.patch b/suse-bump-xen-version.patch index f365ca7..9440f87 100644 --- a/suse-bump-xen-version.patch +++ b/suse-bump-xen-version.patch @@ -26,7 +26,7 @@ Index: libvirt-7.0.0/src/libxl/libxl_domain.c =================================================================== --- libvirt-7.0.0.orig/src/libxl/libxl_domain.c +++ libvirt-7.0.0/src/libxl/libxl_domain.c -@@ -1013,8 +1013,8 @@ libxlDomainSetVcpuAffinities(libxlDriver +@@ -1007,8 +1007,8 @@ libxlDomainSetVcpuAffinities(libxlDriver static int libxlDomainFreeMem(libxl_ctx *ctx, libxl_domain_config *d_config) { @@ -37,7 +37,7 @@ Index: libvirt-7.0.0/src/libxl/libxl_domain.c int32_t target_mem; int tries = 3; int wait_secs = 10; -@@ -1404,7 +1404,7 @@ libxlDomainStart(libxlDriverPrivatePtr d +@@ -1398,7 +1398,7 @@ libxlDomainStart(libxlDriverPrivatePtr d params.stream_version = restore_ver; #endif ret = libxl_domain_create_restore(cfg->ctx, &d_config, &domid, diff --git a/suse-libvirt-guests-service.patch b/suse-libvirt-guests-service.patch index 00b3e6d..b725b9f 100644 --- a/suse-libvirt-guests-service.patch +++ b/suse-libvirt-guests-service.patch @@ -4,14 +4,7 @@ Index: libvirt-7.0.0/tools/libvirt-guests.sh.in =================================================================== --- libvirt-7.0.0.orig/tools/libvirt-guests.sh.in +++ libvirt-7.0.0/tools/libvirt-guests.sh.in -@@ -16,14 +16,13 @@ - # License along with this library. If not, see - # . - -+. /etc/rc.status -+rc_reset -+ - sysconfdir="@sysconfdir@" +@@ -20,10 +20,6 @@ sysconfdir="@sysconfdir@" localstatedir="@localstatedir@" libvirtd="@sbindir@"/libvirtd @@ -22,147 +15,19 @@ Index: libvirt-7.0.0/tools/libvirt-guests.sh.in # Source gettext library. # Make sure this file is recognized as having translations: _("dummy") . "@bindir@"/gettext.sh -@@ -43,9 +42,11 @@ test -f "$sysconfdir"/sysconfig/libvirt- +@@ -43,7 +39,11 @@ test -f "$sysconfdir"/sysconfig/libvirt- . "$sysconfdir"/sysconfig/libvirt-guests LISTFILE="$localstatedir"/lib/libvirt/libvirt-guests -VAR_SUBSYS_LIBVIRT_GUESTS="$localstatedir"/lock/subsys/libvirt-guests -- --RETVAL=0 +if [ -d "$localstatedir"/lock/subsys ]; then + VAR_SUBSYS_LIBVIRT_GUESTS="$localstatedir"/lock/subsys/libvirt-guests +else + VAR_SUBSYS_LIBVIRT_GUESTS="$localstatedir"/lock/libvirt-guests +fi - # retval COMMAND ARGUMENTS... - # run command with arguments and convert non-zero return value to 1 and set -@@ -53,7 +54,7 @@ RETVAL=0 - retval() { - "$@" - if [ $? -ne 0 ]; then -- RETVAL=1 -+ rc_failed 1 - return 1 - else - return 0 -@@ -82,6 +83,26 @@ run_virsh_c() { - ( export LC_ALL=C; run_virsh "$@" ) - } + RETVAL=0 -+await_daemon_up() -+{ -+ uri=$1 -+ i=1 -+ rets=10 -+ run_virsh $uri list > /dev/null 2>&1 -+ while test $? -ne 0 && test $i -lt $rets; do -+ sleep 1 -+ echo -n . -+ i=$(($i + 1)) -+ run_virsh $uri list > /dev/null 2>&1 -+ done -+ if [ $i -eq $rets ]; then -+ eval_gettext "libvirt-guests unable to connect to URI: $uri" -+ echo -+ return 1 -+ fi -+ return 0 -+} -+ - # test_connect URI - # check if URI is reachable - test_connect() -@@ -108,7 +129,7 @@ list_guests() { - local list="$(run_virsh_c "$uri" list --uuid $persistent)" - - if [ $? -ne 0 ]; then -- RETVAL=1 -+ rc_failed 1 - return 1 - fi - -@@ -134,7 +155,7 @@ guest_is_on() { - - guest_running="false" - if [ $? -ne 0 ]; then -- RETVAL=1 -+ rc_failed 1 - return 1 - fi - -@@ -190,6 +211,13 @@ start() { - - test_connect "$uri" || continue - -+ await_daemon_up $uri -+ if [ $? -ne 0 ]; then -+ eval_gettext "Ignoring guests on $uri URI, can't connect" -+ echo -+ continue -+ fi -+ - eval_gettext "Resuming guests on \$uri URI..."; echo - for guest in $list; do - local name="$(guest_name "$uri" "$guest")" -@@ -418,7 +446,7 @@ shutdown_guests_parallel() - timeout=$(($timeout - 1)) - if [ $timeout -le 0 ]; then - eval_gettext "Timeout expired while shutting down domains"; echo -- RETVAL=1 -+ rc_failed 1 - return - fi - else -@@ -449,7 +477,7 @@ stop() { - if [ $SHUTDOWN_TIMEOUT -lt 0 ]; then - gettext "SHUTDOWN_TIMEOUT must be equal or greater than 0" - echo -- RETVAL=6 -+ rc_failed 6 - return - fi - fi -@@ -499,14 +527,14 @@ stop() { - if [ $? -ne 0 ]; then - eval_gettext "Failed to list persistent guests on \$uri" - echo -- RETVAL=1 -+ rc_failed 1 - set +f - return - fi - else - gettext "Failed to list transient guests" - echo -- RETVAL=1 -+ rc_failed 1 - set +f - return - fi -@@ -567,14 +595,13 @@ gueststatus() { - rh_status() { - if [ -f "$LISTFILE" ]; then - gettext "stopped, with saved guests"; echo -- RETVAL=3 -+ rc_failed 3 - else - if [ -f "$VAR_SUBSYS_LIBVIRT_GUESTS" ]; then - gettext "started"; echo -- RETVAL=0 - else - gettext "stopped, with no saved guests"; echo -- RETVAL=3 -+ rc_failed 3 - fi - fi - } -@@ -619,4 +646,4 @@ case "$1" in - usage - ;; - esac --exit $RETVAL -+rc_exit Index: libvirt-7.0.0/tools/libvirt-guests.sysconf =================================================================== --- libvirt-7.0.0.orig/tools/libvirt-guests.sysconf