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".
NB, the qemu capability is called QEMU_CAPS_NO_FAKE_REBOOT for backward
compatibility with running domains started by libvirtd that didn't have
this patch in.
---
src/qemu/qemu_capabilities.c | 9 +++++++++
src/qemu/qemu_capabilities.h | 1 +
src/qemu/qemu_command.c | 2 +-
src/qemu/qemu_driver.c | 6 ++++++
4 files changed, 17 insertions(+), 1 deletions(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 36f47a9..5b9e4a9 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-fake-reboot",
);
struct qemu_feature_flags {
@@ -1008,6 +1009,14 @@ qemuCapsComputeCmdFlags(const char *help,
qemuCapsSet(flags, QEMU_CAPS_VHOST_NET);
}
+ /* Do not use -no-shutdown to implement fake reboot 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 / 1000 == 14 || version / 1000 == 15)
+ qemuCapsSet(flags, QEMU_CAPS_NO_FAKE_REBOOT);
+
/*
* 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 96b7a3b..b4f3ba4 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_FAKE_REBOOT = 74, /* don't fake reboot using -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 ee4b52b..aab4cd9 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_FAKE_REBOOT))
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 f4ee4c3..d2eb881 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_FAKE_REBOOT)) {
+ 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;
--
1.7.6.1