From: Jiri Denemark Date: Wed, 21 Sep 2011 08:25:29 +0000 (+0200) Subject: qemu: Fix shutdown regression with buggy qemu X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=f84aedad090da1e05ccc5651815febba013eb3ad;p=libvirt.git qemu: Fix shutdown regression with buggy qemu 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. The affected versions of QEMU do not quit on SIGTERM if started with -no-shutdown, which we use to implement fake reboot. Since -no-shutdown tells QEMU not to quit automatically on guest shutdown, domains started using the affected QEMU cannot be shutdown properly and stay in a paused state. This patch disables fake reboot feature on such QEMU by not using -no-shutdown, which makes shutdown work as expected. However, virDomainReboot will not work in this case and it will report "Requested operation is not valid: Reboot is not supported with this QEMU binary". --- diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 36f47a9a66..850d46e766 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", ); struct qemu_feature_flags { @@ -1008,6 +1009,13 @@ qemuCapsComputeCmdFlags(const char *help, qemuCapsSet(flags, QEMU_CAPS_VHOST_NET); } + /* Do not use -no-shutdown if qemu doesn't support it or SIGTERM handling + * is most likely buggy when used with -no-shutdown (which applies for qemu + * 0.14.* and 0.15.*) + */ + if (strstr(help, "-no-shutdown") && (version < 14000 || version > 15999)) + qemuCapsSet(flags, QEMU_CAPS_NO_SHUTDOWN); + /* * Handling of -incoming arg with varying features * -incoming tcp (kvm >= 79, qemu >= 0.10.0) diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 96b7a3b18b..74d3ab2422 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 = 74, /* usable -no-shutdown */ QEMU_CAPS_LAST, /* this must always be the last item */ }; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index ee4b52beb9..0adc56a5f9 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -3574,7 +3574,7 @@ qemuBuildCommandLine(virConnectPtr conn, * when QEMU stops. If we use no-shutdown, then we can * watch for this event and do a soft/warm reboot. */ - if (monitor_json) + if (monitor_json && qemuCapsGet(qemuCaps, QEMU_CAPS_NO_SHUTDOWN)) virCommandAddArg(cmd, "-no-shutdown"); if (!(def->features & (1 << VIR_DOMAIN_FEATURE_ACPI))) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index f4ee4c3f8f..67c43ab203 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1557,6 +1557,12 @@ static int qemuDomainReboot(virDomainPtr dom, unsigned int flags) { priv = vm->privateData; if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_MONITOR_JSON)) { + if (!qemuCapsGet(priv->qemuCaps, QEMU_CAPS_NO_SHUTDOWN)) { + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("Reboot is not supported with this QEMU binary")); + goto cleanup; + } + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) goto cleanup; diff --git a/tests/qemuhelptest.c b/tests/qemuhelptest.c index ffd30e2935..4a4070a154 100644 --- a/tests/qemuhelptest.c +++ b/tests/qemuhelptest.c @@ -152,7 +152,8 @@ mymain(void) QEMU_CAPS_KVM, QEMU_CAPS_DRIVE_FORMAT, QEMU_CAPS_MEM_PATH, - QEMU_CAPS_TDF); + QEMU_CAPS_TDF, + QEMU_CAPS_NO_SHUTDOWN); DO_TEST("kvm-83-rhel56", 9001, 1, 83, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -177,7 +178,8 @@ mymain(void) QEMU_CAPS_TDF, QEMU_CAPS_DRIVE_READONLY, QEMU_CAPS_SMBIOS_TYPE, - QEMU_CAPS_SPICE); + QEMU_CAPS_SPICE, + QEMU_CAPS_NO_SHUTDOWN); DO_TEST("qemu-0.10.5", 10005, 0, 0, QEMU_CAPS_KQEMU, QEMU_CAPS_VNC_COLON, @@ -196,7 +198,8 @@ mymain(void) QEMU_CAPS_SDL, QEMU_CAPS_RTC_TD_HACK, QEMU_CAPS_NO_HPET, - QEMU_CAPS_VGA_NONE); + QEMU_CAPS_VGA_NONE, + QEMU_CAPS_NO_SHUTDOWN); DO_TEST("qemu-kvm-0.10.5", 10005, 1, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -221,7 +224,8 @@ mymain(void) QEMU_CAPS_NO_KVM_PIT, QEMU_CAPS_TDF, QEMU_CAPS_NESTING, - QEMU_CAPS_VGA_NONE); + QEMU_CAPS_VGA_NONE, + QEMU_CAPS_NO_SHUTDOWN); DO_TEST("kvm-86", 10050, 1, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -246,7 +250,8 @@ mymain(void) QEMU_CAPS_TDF, QEMU_CAPS_NESTING, QEMU_CAPS_SMBIOS_TYPE, - QEMU_CAPS_VGA_NONE); + QEMU_CAPS_VGA_NONE, + QEMU_CAPS_NO_SHUTDOWN); DO_TEST("qemu-kvm-0.11.0-rc2", 10092, 1, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -276,7 +281,8 @@ mymain(void) QEMU_CAPS_NESTING, QEMU_CAPS_NAME_PROCESS, QEMU_CAPS_SMBIOS_TYPE, - QEMU_CAPS_VGA_NONE); + QEMU_CAPS_VGA_NONE, + QEMU_CAPS_NO_SHUTDOWN); DO_TEST("qemu-0.12.1", 12001, 0, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -306,7 +312,8 @@ mymain(void) QEMU_CAPS_SMBIOS_TYPE, QEMU_CAPS_VGA_NONE, QEMU_CAPS_MIGRATE_QEMU_FD, - QEMU_CAPS_DRIVE_AIO); + QEMU_CAPS_DRIVE_AIO, + QEMU_CAPS_NO_SHUTDOWN); DO_TEST("qemu-kvm-0.12.1.2-rhel60", 12001, 1, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -350,7 +357,8 @@ mymain(void) QEMU_CAPS_DEVICE_SPICEVMC, QEMU_CAPS_PIIX3_USB_UHCI, QEMU_CAPS_PIIX4_USB_UHCI, - QEMU_CAPS_USB_HUB); + QEMU_CAPS_USB_HUB, + QEMU_CAPS_NO_SHUTDOWN); DO_TEST("qemu-kvm-0.12.3", 12003, 1, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -387,7 +395,8 @@ mymain(void) QEMU_CAPS_SMBIOS_TYPE, QEMU_CAPS_VGA_NONE, QEMU_CAPS_MIGRATE_QEMU_FD, - QEMU_CAPS_DRIVE_AIO); + QEMU_CAPS_DRIVE_AIO, + QEMU_CAPS_NO_SHUTDOWN); DO_TEST("qemu-kvm-0.13.0", 13000, 1, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -439,7 +448,8 @@ mymain(void) QEMU_CAPS_PIIX4_USB_UHCI, QEMU_CAPS_VT82C686B_USB_UHCI, QEMU_CAPS_PCI_OHCI, - QEMU_CAPS_USB_HUB); + QEMU_CAPS_USB_HUB, + QEMU_CAPS_NO_SHUTDOWN); DO_TEST("qemu-kvm-0.12.1.2-rhel61", 12001, 1, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -487,7 +497,8 @@ mymain(void) QEMU_CAPS_VIRTIO_IOEVENTFD, QEMU_CAPS_PIIX3_USB_UHCI, QEMU_CAPS_PIIX4_USB_UHCI, - QEMU_CAPS_USB_HUB); + QEMU_CAPS_USB_HUB, + QEMU_CAPS_NO_SHUTDOWN); return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/tests/qemuxml2argvdata/qemuxml2argv-monitor-json.args b/tests/qemuxml2argvdata/qemuxml2argv-monitor-json.args index 8d8e43ebd1..e04cdec8f3 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-monitor-json.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-monitor-json.args @@ -1,5 +1,5 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -chardev socket,\ id=charmonitor,path=/tmp/test-monitor,server,nowait -mon chardev=charmonitor,\ -id=monitor,mode=control -no-shutdown -no-acpi -boot c -hda /dev/hda1 -usb -device \ +id=monitor,mode=control -no-acpi -boot c -hda /dev/hda1 -usb -device \ virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-no-shutdown.args b/tests/qemuxml2argvdata/qemuxml2argv-no-shutdown.args new file mode 100644 index 0000000000..1464d09cb8 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-no-shutdown.args @@ -0,0 +1,21 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +/usr/bin/qemu \ +-S \ +-M pc \ +-m 214 \ +-smp 1 \ +-nographic \ +-nodefconfig \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/test-monitor,server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-no-shutdown \ +-no-acpi \ +-boot c \ +-hda /dev/hda1 \ +-usb \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-no-shutdown.xml b/tests/qemuxml2argvdata/qemuxml2argv-no-shutdown.xml new file mode 100644 index 0000000000..1901715de7 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-no-shutdown.xml @@ -0,0 +1,24 @@ + + encryptdisk + 496898a6-e6ff-f7c8-5dc2-3cf410945ee9 + 219100 + 219100 + 1 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu + + + + + + + + diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index fcb20bbd62..1dc6a01759 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -578,6 +578,9 @@ mymain(void) json = true; DO_TEST("monitor-json", false, QEMU_CAPS_DEVICE, QEMU_CAPS_CHARDEV, QEMU_CAPS_MONITOR_JSON, QEMU_CAPS_NODEFCONFIG); + DO_TEST("no-shutdown", false, QEMU_CAPS_DEVICE, + QEMU_CAPS_CHARDEV, QEMU_CAPS_MONITOR_JSON, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_NO_SHUTDOWN); json = false; free(driver.stateDir);