QEMU reports win-dmp as available only when the guest is Windows
and 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.

Signed-off-by: Denis V. Lunev <[email protected]>
---
 src/qemu/qemu_driver.c | 30 ++++++++++++++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 8ec9e1f9c4..b59a714a81 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -3532,6 +3532,31 @@ getAutoDumpPath(virQEMUDriver *driver,
     return g_strdup_printf("%s/%s-%s", cfg->autoDumpPath, domname, nowstr);
 }
 
+/* win-dmp is reported only for a Windows guest that has published a
+ * vmcoreinfo dump header, so prefer it whenever QEMU confirms it. */
+static unsigned int
+qemuDomainGetAutoDumpFormat(virDomainObj *vm)
+{
+    qemuDomainObjPrivate *priv = vm->privateData;
+    unsigned int dumpformat = VIR_DOMAIN_CORE_DUMP_FORMAT_RAW;
+    int rc;
+
+    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 +3583,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 +3603,7 @@ processWatchdogEvent(virQEMUDriver *driver,
     virDomainObjEndAsyncJob(vm);
 }
 
+
 static int
 doCoreDumpToAutoDumpPath(virQEMUDriver *driver,
                          virDomainObj *vm,
@@ -3592,7 +3618,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

Reply via email to