[libvirt] [PATCH] qemu: Fix shutdown regression
Dave Allan
dallan at redhat.com
Tue Sep 20 18:06:49 UTC 2011
On Tue, Sep 20, 2011 at 07:39:15PM +0200, Jiri Denemark wrote:
> The commit that prevents disk corruption on domain shutdown
> (96fc4784177ecb70357518fa863442455e45ad0e) causes regression with QEMU
> 0.14.* and 0.15.* because of a regression bug in QEMU that was fixed
> only recently in QEMU git. With affected QEMU binaries, domains cannot
> be shutdown properly and stay in a paused state. This patch tries to
> avoid this by sending SIGKILL to 0.1[45].* QEMU processes. Though we
> wait a bit more between sending SIGTERM and SIGKILL to reduce the
> possibility of virtual disk corruption.
IMO, SIGKILL should only be sent at the explicit direction of the
user, saying in effect, I'm ok with possible data corruption, I want
the VM killed unconditionally. I would rather leave VMs paused than
risk corrupting data. Let's get as much input as we can from the qemu
folks before we go down this path.
Dave
> ---
> src/qemu/qemu_capabilities.c | 7 +++++++
> src/qemu/qemu_capabilities.h | 1 +
> src/qemu/qemu_process.c | 19 +++++++++++++------
> 3 files changed, 21 insertions(+), 6 deletions(-)
>
> diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
> index 36f47a9..823c500 100644
> --- a/src/qemu/qemu_capabilities.c
> +++ b/src/qemu/qemu_capabilities.c
> @@ -136,6 +136,7 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST,
> "pci-ohci",
> "usb-redir",
> "usb-hub",
> + "no-shutdown-bug",
> );
>
> struct qemu_feature_flags {
> @@ -1049,6 +1050,12 @@ qemuCapsComputeCmdFlags(const char *help,
>
> if (version >= 13000)
> qemuCapsSet(flags, QEMU_CAPS_PCI_MULTIFUNCTION);
> +
> + /* QEMU version 0.14.* and 0.15.* are known not to handle SIGTERM
> + * properly when started with -no-shutdown
> + */
> + if (version >= 14000 && version <= 15999)
> + qemuCapsSet(flags, QEMU_CAPS_NO_SHUTDOWN_BUG);
> }
>
> /* We parse the output of 'qemu -help' to get the QEMU
> diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
> index 96b7a3b..53d5ace 100644
> --- a/src/qemu/qemu_capabilities.h
> +++ b/src/qemu/qemu_capabilities.h
> @@ -110,6 +110,7 @@ enum qemuCapsFlags {
> QEMU_CAPS_PCI_OHCI = 71, /* -device pci-ohci */
> QEMU_CAPS_USB_REDIR = 72, /* -device usb-redir */
> QEMU_CAPS_USB_HUB = 73, /* -device usb-hub */
> + QEMU_CAPS_NO_SHUTDOWN_BUG = 74, /* -no-shutdown doesn't exit on SIGTERM */
>
> QEMU_CAPS_LAST, /* this must always be the last item */
> };
> diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
> index 3baaa19..3311699 100644
> --- a/src/qemu/qemu_process.c
> +++ b/src/qemu/qemu_process.c
> @@ -434,6 +434,7 @@ qemuProcessHandleShutdown(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
> virDomainObjPtr vm)
> {
> qemuDomainObjPrivatePtr priv = vm->privateData;
> + bool gracefully = true;
> VIR_DEBUG("vm=%p", vm);
>
> virDomainObjLock(vm);
> @@ -443,6 +444,12 @@ qemuProcessHandleShutdown(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
> goto cleanup;
> }
>
> + if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_NO_SHUTDOWN_BUG)) {
> + VIR_DEBUG("Emulator is likely affected by -no-shutdown bug;"
> + " we will not avoid sending SIGKILL to it");
> + gracefully = false;
> + }
> +
> priv->gotShutdown = true;
> if (priv->fakeReboot) {
> virDomainObjRef(vm);
> @@ -452,12 +459,12 @@ qemuProcessHandleShutdown(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
> qemuProcessFakeReboot,
> vm) < 0) {
> VIR_ERROR(_("Failed to create reboot thread, killing domain"));
> - qemuProcessKill(vm, true);
> + qemuProcessKill(vm, gracefully);
> if (virDomainObjUnref(vm) == 0)
> vm = NULL;
> }
> } else {
> - qemuProcessKill(vm, true);
> + qemuProcessKill(vm, gracefully);
> }
>
> cleanup:
> @@ -3227,15 +3234,15 @@ void qemuProcessKill(virDomainObjPtr vm, bool gracefully)
> }
>
> /* This loop sends SIGTERM, then waits a few iterations
> - * (1.6 seconds) to see if it dies. If still alive then
> + * (3 seconds) to see if it dies. If still alive then
> * it does SIGKILL, and waits a few more iterations (1.6
> * seconds more) to confirm that it has really gone.
> */
> - for (i = 0 ; i < 15 ; i++) {
> + for (i = 0 ; i < 23 ; i++) {
> int signum;
> if (i == 0)
> signum = SIGTERM;
> - else if (i == 8)
> + else if (i == 15)
> signum = SIGKILL;
> else
> signum = 0; /* Just check for existence */
> @@ -3249,7 +3256,7 @@ void qemuProcessKill(virDomainObjPtr vm, bool gracefully)
> break;
> }
>
> - if (i == 0 && gracefully)
> + if (gracefully)
> break;
>
> usleep(200 * 1000);
> --
> 1.7.6.1
>
> --
> libvir-list mailing list
> libvir-list at redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list
More information about the libvir-list
mailing list