Where QEMU_CAPS_WIN_DMP_GUEST_AWARE is present, QEMU reports win-dmp as available only for a guest that has published a vmcoreinfo dump header. In that case prefer it over the elf default: converting an elf dump into a Windows-debuggable format afterwards is possible but complicated and unreliable. Add qemuDomainGetAutoDumpFormat(), which probes win-dmp support right before an auto-triggered dump and falls back to elf otherwise. Use it from both doCoreDumpToAutoDumpPath() (on_crash) and processWatchdogEvent() (watchdog dump). virDomainCoreDump() and virDomainCoreDumpWithFormat() are left untouched, since RAW there is a documented part of their API contract, standing in for an explicit caller request rather than an internal default. The probe is best-effort: reset any error left by a failed monitor call or QMP command, so it cannot leak past a dump that otherwise succeeds. Without the capability the probe is skipped: older QEMU offers win-dmp on any x86 machine, where the resulting dump is useless. Signed-off-by: Denis V. Lunev <den@openvz.org> --- NEWS.rst | 7 +++++++ src/qemu/qemu_driver.c | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/NEWS.rst b/NEWS.rst index ae4d8c18a5..3dadb6d4f3 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -19,6 +19,13 @@ v12.7.0 (unreleased) * **Improvements** + * qemu: Select the win-dmp format for Windows guest crash dumps + + Dumps triggered by ``<on_crash>`` and by watchdog handling used QEMU's elf + default, which WinDbg cannot load. Where QEMU reports the format as + available only to a guest that can use it, such dumps are now written in + win-dmp format instead. + * **Bug fixes** diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 44b41726fb..cfabaf0746 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3532,6 +3532,34 @@ getAutoDumpPath(virQEMUDriver *driver, return g_strdup_printf("%s/%s-%s", cfg->autoDumpPath, domname, nowstr); } +/* Older QEMU offers win-dmp on any x86 machine, so trust the capability + * query only where QEMU says the answer depends on the guest. */ +static unsigned int +qemuDomainGetAutoDumpFormat(virDomainObj *vm) +{ + qemuDomainObjPrivate *priv = vm->privateData; + unsigned int dumpformat = VIR_DOMAIN_CORE_DUMP_FORMAT_RAW; + int rc; + + if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_WIN_DMP_GUEST_AWARE)) + return dumpformat; + + if (qemuDomainObjEnterMonitorAsync(vm, VIR_ASYNC_JOB_DUMP) < 0) { + virResetLastError(); + return dumpformat; + } + + rc = qemuMonitorGetDumpGuestMemoryCapability(priv->mon, "win-dmp"); + if (rc < 0) + virResetLastError(); + else if (rc > 0) + dumpformat = VIR_DOMAIN_CORE_DUMP_FORMAT_WIN_DMP; + + qemuDomainObjExitMonitor(vm); + return dumpformat; +} + + static void processWatchdogEvent(virQEMUDriver *driver, virDomainObj *vm, @@ -3558,7 +3586,7 @@ processWatchdogEvent(virQEMUDriver *driver, flags |= cfg->autoDumpBypassCache ? VIR_DUMP_BYPASS_CACHE: 0; if ((ret = doCoreDump(driver, vm, dumpfile, flags, - VIR_DOMAIN_CORE_DUMP_FORMAT_RAW)) < 0) + qemuDomainGetAutoDumpFormat(vm))) < 0) virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("Dump failed")); @@ -3578,6 +3606,7 @@ processWatchdogEvent(virQEMUDriver *driver, virDomainObjEndAsyncJob(vm); } + static int doCoreDumpToAutoDumpPath(virQEMUDriver *driver, virDomainObj *vm, @@ -3592,7 +3621,7 @@ doCoreDumpToAutoDumpPath(virQEMUDriver *driver, flags |= cfg->autoDumpBypassCache ? VIR_DUMP_BYPASS_CACHE: 0; if ((ret = doCoreDump(driver, vm, dumpfile, flags, - VIR_DOMAIN_CORE_DUMP_FORMAT_RAW)) < 0) + qemuDomainGetAutoDumpFormat(vm))) < 0) virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("Dump failed")); return ret; -- 2.53.0