[libvirt] [PATCH v6 0/4] support dumping guest memory in compressed format

dumping guest's memory is introduced without compression supported, but now qemu can dump guest's memory in kdump-compressed format. This patchset is used to add support in libvirt side to let qemu do the dump in compressed format and please refer the following address to see implementation of the qemu side, the lastest version of qemu side is v9. http://lists.nongnu.org/archive/html/qemu-devel/2014-02/msg03016.html ChangLog: Changes from v5 to v6: 1. add qemuMonitorGetDumpGuestMemoryCapability API to check the available dump format Changes from v4 to v5: 1. modify some restriction check Changes from v3 to v4: 1. dropping patch "add dump_memory_format in qemu.conf" 2. fix to follow some conventions Changes from v2 to v3: 1. address Jiri Denemark's comment about adding a new public API instead of changing an old one. Changes from v1 to v2: 1. address Daniel P. Berrange's comment about using a new parameter to replace flags like VIR_DUMP_COMPRESS_ZLIB. qiaonuohan (4): add new virDomainCoreDumpWithFormat API qemu: add qemuMonitorGetDumpGuestMemoryCapability qemu: add support for virDomainCoreDumpWithFormat API allow "virsh dump --memory-only" specify dump format include/libvirt/libvirt.h.in | 8 ++++ src/driver.h | 7 ++++ src/libvirt.c | 92 ++++++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 5 +++ src/qemu/qemu_driver.c | 50 +++++++++++++++++++----- src/qemu/qemu_monitor.c | 27 +++++++++++-- src/qemu/qemu_monitor.h | 6 ++- src/qemu/qemu_monitor_json.c | 86 ++++++++++++++++++++++++++++++++++++++--- src/qemu/qemu_monitor_json.h | 6 ++- src/remote/remote_driver.c | 1 + src/remote/remote_protocol.x | 15 +++++++- src/remote_protocol-structs | 7 ++++ src/test/test_driver.c | 21 ++++++++-- tests/qemumonitorjsontest.c | 2 +- tools/virsh-domain.c | 30 +++++++++++++-- tools/virsh.pod | 6 +++ 16 files changed, 342 insertions(+), 27 deletions(-) -- 1.8.5.3

--memory-only option is introduced without compression supported. Now qemu has support dumping domain's memory in kdump-compressed format. This patch is adding new virDomainCoreDumpWithFormat API, so that the format in which qemu dumps domain's memory can be specified. Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com> --- include/libvirt/libvirt.h.in | 8 ++++ src/driver.h | 7 ++++ src/libvirt.c | 92 ++++++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 5 +++ src/remote/remote_driver.c | 1 + src/remote/remote_protocol.x | 15 +++++++- src/remote_protocol-structs | 7 ++++ src/test/test_driver.c | 21 ++++++++-- 8 files changed, 152 insertions(+), 4 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 295d551..a0a8722 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -1731,6 +1731,14 @@ int virDomainCoreDump (virDomainPtr domain, unsigned int flags); /* + * Domain core dump with format specified + */ +int virDomainCoreDumpWithFormat (virDomainPtr domain, + const char *to, + const char *dumpformat, + unsigned int flags); + +/* * Screenshot of current domain console */ char * virDomainScreenshot (virDomainPtr domain, diff --git a/src/driver.h b/src/driver.h index fbfaac4..784c20b 100644 --- a/src/driver.h +++ b/src/driver.h @@ -306,6 +306,12 @@ typedef int const char *to, unsigned int flags); +typedef int +(*virDrvDomainCoreDumpWithFormat)(virDomainPtr domain, + const char *to, + const char *dumpformat, + unsigned int flags); + typedef char * (*virDrvDomainScreenshot)(virDomainPtr domain, virStreamPtr stream, @@ -1200,6 +1206,7 @@ struct _virDriver { virDrvDomainSaveImageGetXMLDesc domainSaveImageGetXMLDesc; virDrvDomainSaveImageDefineXML domainSaveImageDefineXML; virDrvDomainCoreDump domainCoreDump; + virDrvDomainCoreDumpWithFormat domainCoreDumpWithFormat; virDrvDomainScreenshot domainScreenshot; virDrvDomainSetVcpus domainSetVcpus; virDrvDomainSetVcpusFlags domainSetVcpusFlags; diff --git a/src/libvirt.c b/src/libvirt.c index a385935..57dfa6b 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -2997,6 +2997,98 @@ error: return -1; } +/** + * virDomainCoreDumpWithFormat: + * @domain: a domain object + * @to: path for the core file + * @dumpformat: format of domain memory's dump + * @flags: bitwise-OR of virDomainCoreDumpFlags + * + * This method will dump the core of a domain on a given file for analysis. + * Note that for remote Xen Daemon the file path will be interpreted in + * the remote host. Hypervisors may require the user to manually ensure + * proper permissions on the file named by @to. + * + * If @flags includes VIR_DUMP_MEMORY_ONLY and @dumpformat is set, libvirt + * will ask qemu dump domain's memory in the format specified by @dumpformat. + * + * If @flags includes VIR_DUMP_CRASH, then leave the guest shut off with + * a crashed state after the dump completes. If @flags includes + * VIR_DUMP_LIVE, then make the core dump while continuing to allow + * the guest to run; otherwise, the guest is suspended during the dump. + * VIR_DUMP_RESET flag forces reset of the quest after dump. + * The above three flags are mutually exclusive. + * + * Additionally, if @flags includes VIR_DUMP_BYPASS_CACHE, then libvirt + * will attempt to bypass the file system cache while creating the file, + * or fail if it cannot do so for the given system; this can allow less + * pressure on file system cache, but also risks slowing saves to NFS. + * + * Returns 0 in case of success and -1 in case of failure. + */ +int +virDomainCoreDumpWithFormat(virDomainPtr domain, const char *to, const char + *dumpformat, unsigned int flags) +{ + virConnectPtr conn; + + VIR_DOMAIN_DEBUG(domain, "to=%s, dumpformat=%s, flags=%x", to, dumpformat, + flags); + + virResetLastError(); + + virCheckDomainReturn(domain, -1); + conn = domain->conn; + + virCheckReadOnlyGoto(conn->flags, error); + virCheckNonNullArgGoto(to, error); + + if ((flags & VIR_DUMP_CRASH) && (flags & VIR_DUMP_LIVE)) { + virReportInvalidArg(flags, "%s", + _("crash and live flags are mutually exclusive")); + goto error; + } + + if ((flags & VIR_DUMP_CRASH) && (flags & VIR_DUMP_RESET)) { + virReportInvalidArg(flags, "%s", + _("crash and reset flags are mutually exclusive")); + goto error; + } + + if ((flags & VIR_DUMP_LIVE) && (flags & VIR_DUMP_RESET)) { + virReportInvalidArg(flags, "%s", + _("live and reset flags are mutually exclusive")); + goto error; + } + + if (conn->driver->domainCoreDumpWithFormat) { + int ret; + char *absolute_to; + + /* We must absolutize the file path as the save is done out of process */ + if (virFileAbsPath(to, &absolute_to) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("could not build absolute core file path")); + goto error; + } + + ret = conn->driver->domainCoreDumpWithFormat(domain, absolute_to, + dumpformat, flags); + + VIR_FREE(absolute_to); + + if (ret < 0) + goto error; + return ret; + } + + virReportUnsupportedError(); + +error: + virDispatchError(domain->conn); + return -1; +} + /** * virDomainScreenshot: diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 6ed6ce6..9ab0c92 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -645,5 +645,10 @@ LIBVIRT_1.2.1 { virConnectNetworkEventDeregisterAny; } LIBVIRT_1.1.3; +LIBVIRT_1.2.3 { + global: + virDomainCoreDumpWithFormat; +} LIBVIRT_1.2.1; + # .... define new API here using predicted next version number .... diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 955465a..0a15267 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -7516,6 +7516,7 @@ static virDriver remote_driver = { .domainSaveImageGetXMLDesc = remoteDomainSaveImageGetXMLDesc, /* 0.9.4 */ .domainSaveImageDefineXML = remoteDomainSaveImageDefineXML, /* 0.9.4 */ .domainCoreDump = remoteDomainCoreDump, /* 0.3.0 */ + .domainCoreDumpWithFormat = remoteDomainCoreDumpWithFormat, /* 1.2.3 */ .domainScreenshot = remoteDomainScreenshot, /* 0.9.2 */ .domainSetVcpus = remoteDomainSetVcpus, /* 0.3.0 */ .domainSetVcpusFlags = remoteDomainSetVcpusFlags, /* 0.8.5 */ diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index f1f2359..3f894ee 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -904,6 +904,13 @@ struct remote_domain_core_dump_args { unsigned int flags; }; +struct remote_domain_core_dump_with_format_args { + remote_nonnull_domain dom; + remote_nonnull_string to; + remote_string dumpformat; + unsigned int flags; +}; + struct remote_domain_screenshot_args { remote_nonnull_domain dom; unsigned int screen; @@ -5262,5 +5269,11 @@ enum remote_procedure { * @generate: both * @acl: none */ - REMOTE_PROC_DOMAIN_EVENT_CALLBACK_DEVICE_REMOVED = 333 + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_DEVICE_REMOVED = 333, + + /** + * @generate: both + * @acl: domain:core_dump + */ + REMOTE_PROC_DOMAIN_CORE_DUMP_WITH_FORMAT = 334 }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 5636d55..c2f7665 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -557,6 +557,12 @@ struct remote_domain_core_dump_args { remote_nonnull_string to; u_int flags; }; +struct remote_domain_core_dump_with_format_args { + remote_nonnull_domain dom; + remote_nonnull_string to; + remote_string dumpformat; + u_int flags; +}; struct remote_domain_screenshot_args { remote_nonnull_domain dom; u_int screen; @@ -2755,4 +2761,5 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_BALLOON_CHANGE = 331, REMOTE_PROC_DOMAIN_EVENT_CALLBACK_PMSUSPEND_DISK = 332, REMOTE_PROC_DOMAIN_EVENT_CALLBACK_DEVICE_REMOVED = 333, + REMOTE_PROC_DOMAIN_CORE_DUMP_WITH_FORMAT = 334, }; diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 6806ffd..2505998 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -2427,9 +2427,10 @@ testDomainRestore(virConnectPtr conn, return testDomainRestoreFlags(conn, path, NULL, 0); } -static int testDomainCoreDump(virDomainPtr domain, - const char *to, - unsigned int flags) +static int testDomainCoreDumpWithFormat(virDomainPtr domain, + const char *to, + const char *dumpformat, + unsigned int flags) { testConnPtr privconn = domain->conn->privateData; int fd = -1; @@ -2467,6 +2468,13 @@ static int testDomainCoreDump(virDomainPtr domain, goto cleanup; } + /* we don't support dumpformat in test driver */ + if (dumpformat != NULL) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("dumpformat is not supported here")); + goto cleanup; + } + if (flags & VIR_DUMP_CRASH) { testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_CRASHED); event = virDomainEventLifecycleNewFromObj(privdom, @@ -2490,6 +2498,12 @@ cleanup: return ret; } +static int testDomainCoreDump(virDomainPtr domain, + const char *to, + unsigned int flags) { + return testDomainCoreDumpWithFormat(domain, to, NULL, flags); +} + static char *testDomainGetOSType(virDomainPtr dom ATTRIBUTE_UNUSED) { char *ret; @@ -7359,6 +7373,7 @@ static virDriver testDriver = { .domainRestore = testDomainRestore, /* 0.3.2 */ .domainRestoreFlags = testDomainRestoreFlags, /* 0.9.4 */ .domainCoreDump = testDomainCoreDump, /* 0.3.2 */ + .domainCoreDumpWithFormat = testDomainCoreDumpWithFormat, /* 1.2.3 */ .domainSetVcpus = testDomainSetVcpus, /* 0.1.4 */ .domainSetVcpusFlags = testDomainSetVcpusFlags, /* 0.8.5 */ .domainGetVcpusFlags = testDomainGetVcpusFlags, /* 0.8.5 */ -- 1.8.5.3

On Sun, Mar 16, 2014 at 06:07:07AM +0000, qiaonuohan@cn.fujitsu.com wrote:
--memory-only option is introduced without compression supported. Now qemu has support dumping domain's memory in kdump-compressed format. This patch is adding new virDomainCoreDumpWithFormat API, so that the format in which qemu dumps domain's memory can be specified.
Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com> --- include/libvirt/libvirt.h.in | 8 ++++ src/driver.h | 7 ++++ src/libvirt.c | 92 ++++++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 5 +++ src/remote/remote_driver.c | 1 + src/remote/remote_protocol.x | 15 +++++++- src/remote_protocol-structs | 7 ++++ src/test/test_driver.c | 21 ++++++++-- 8 files changed, 152 insertions(+), 4 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 295d551..a0a8722 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -1731,6 +1731,14 @@ int virDomainCoreDump (virDomainPtr domain, unsigned int flags);
/* + * Domain core dump with format specified + */ +int virDomainCoreDumpWithFormat (virDomainPtr domain, + const char *to, + const char *dumpformat,
NACK, please put this back as an enum as it was in previous versions. This is exposing QEMU implementation names in the API which is bad.
+ unsigned int flags);
Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

This patch adds qemuMonitorGetDumpGuestMemoryCapability, which is used to check whether the specified dump-guest-memory format is supported by qemu. Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com> --- src/qemu/qemu_monitor.c | 21 ++++++++++++++ src/qemu/qemu_monitor.h | 3 ++ src/qemu/qemu_monitor_json.c | 65 ++++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 3 ++ 4 files changed, 92 insertions(+) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index a2769db..8104104 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2344,6 +2344,27 @@ int qemuMonitorMigrateCancel(qemuMonitorPtr mon) return ret; } +/** + * Returns 1 if @capability is supported, 0 if it's not, or -1 on error. + */ +int qemuMonitorGetDumpGuestMemoryCapability(qemuMonitorPtr mon, + const char *capability) +{ + VIR_DEBUG("mon=%p capability=%s", mon, capability); + + if (!mon) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("monitor must not be NULL")); + return -1; + } + + /* No capability is supported without JSON monitor */ + if (!mon->json) + return 0; + + return qemuMonitorJSONGetDumpGuestMemoryCapability(mon, capability); +} + int qemuMonitorDumpToFd(qemuMonitorPtr mon, int fd) { diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index eabf000..00a6554 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -494,6 +494,9 @@ int qemuMonitorMigrateToUnix(qemuMonitorPtr mon, int qemuMonitorMigrateCancel(qemuMonitorPtr mon); +int qemuMonitorGetDumpGuestMemoryCapability(qemuMonitorPtr mon, + const char *capability); + int qemuMonitorDumpToFd(qemuMonitorPtr mon, int fd); diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index ee3ae15..2cf706c 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -2635,6 +2635,71 @@ int qemuMonitorJSONMigrateCancel(qemuMonitorPtr mon) } int +qemuMonitorJSONGetDumpGuestMemoryCapability(qemuMonitorPtr mon, + const char *capability) +{ + int ret; + virJSONValuePtr cmd; + virJSONValuePtr reply = NULL; + virJSONValuePtr caps; + virJSONValuePtr formats; + size_t i; + + if (!(cmd = qemuMonitorJSONMakeCommand("query-dump-guest-memory-capability", + NULL))) + return -1; + + ret = qemuMonitorJSONCommand(mon, cmd, &reply); + + if (ret == 0) { + if (qemuMonitorJSONHasError(reply, "CommandNotFound")) + goto cleanup; + ret = qemuMonitorJSONCheckError(cmd, reply); + } + + if (ret < 0) + goto cleanup; + + ret = -1; + + caps = virJSONValueObjectGet(reply, "return"); + if (!caps || caps->type != VIR_JSON_TYPE_OBJECT) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("missing dump guest memory capabilities")); + goto cleanup; + } + + formats = virJSONValueObjectGet(caps, "formats"); + if (!formats || formats->type != VIR_JSON_TYPE_ARRAY) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("missing supported dump formats")); + goto cleanup; + } + + for (i = 0; i < virJSONValueArraySize(formats); i++) { + virJSONValuePtr dumpformat = virJSONValueArrayGet(formats, i); + + if (!dumpformat || dumpformat->type != VIR_JSON_TYPE_STRING) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("missing entry in supported dump formats")); + goto cleanup; + } + + if (STREQ(virJSONValueGetString(dumpformat), capability)) { + ret = 1; + goto cleanup; + } + + ret = 0; + } + +cleanup: + virJSONValueFree(cmd); + virJSONValueFree(reply); + return ret; +} + +int qemuMonitorJSONDump(qemuMonitorPtr mon, const char *protocol) { diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index a93c51e..37e9456 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -147,6 +147,9 @@ int qemuMonitorJSONGetSpiceMigrationStatus(qemuMonitorPtr mon, int qemuMonitorJSONMigrateCancel(qemuMonitorPtr mon); +int qemuMonitorJSONGetDumpGuestMemoryCapability(qemuMonitorPtr mon, + const char *capability); + int qemuMonitorJSONDump(qemuMonitorPtr mon, const char *protocol); -- 1.8.5.3

This patch makes qemu driver support virDomainCoreDumpWithFormat API. Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com> --- src/qemu/qemu_driver.c | 50 ++++++++++++++++++++++++++++++++++++-------- src/qemu/qemu_monitor.c | 6 +++--- src/qemu/qemu_monitor.h | 3 ++- src/qemu/qemu_monitor_json.c | 21 ++++++++++++++----- src/qemu/qemu_monitor_json.h | 3 ++- tests/qemumonitorjsontest.c | 2 +- 6 files changed, 65 insertions(+), 20 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 9aad2dc..868735c 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3389,7 +3389,8 @@ cleanup: } static int qemuDumpToFd(virQEMUDriverPtr driver, virDomainObjPtr vm, - int fd, enum qemuDomainAsyncJob asyncJob) + int fd, enum qemuDomainAsyncJob asyncJob, + const char *dumpformat) { qemuDomainObjPrivatePtr priv = vm->privateData; int ret = -1; @@ -3409,7 +3410,20 @@ static int qemuDumpToFd(virQEMUDriverPtr driver, virDomainObjPtr vm, if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0) return -1; - ret = qemuMonitorDumpToFd(priv->mon, fd); + if (dumpformat) { + ret = qemuMonitorGetDumpGuestMemoryCapability(priv->mon, dumpformat); + + if (ret <= 0) { + virReportError(VIR_ERR_INVALID_ARG, + _("unsupported dumpformat '%s'"), dumpformat); + ret = -1; + goto cleanup; + } + } + + ret = qemuMonitorDumpToFd(priv->mon, fd, dumpformat); + +cleanup: qemuDomainObjExitMonitor(driver, vm); return ret; @@ -3420,7 +3434,8 @@ doCoreDump(virQEMUDriverPtr driver, virDomainObjPtr vm, const char *path, virQEMUSaveFormat compress, - unsigned int dump_flags) + unsigned int dump_flags, + const char *dumpformat) { int fd = -1; int ret = -1; @@ -3450,8 +3465,15 @@ doCoreDump(virQEMUDriverPtr driver, goto cleanup; if (dump_flags & VIR_DUMP_MEMORY_ONLY) { - ret = qemuDumpToFd(driver, vm, fd, QEMU_ASYNC_JOB_DUMP); + ret = qemuDumpToFd(driver, vm, fd, QEMU_ASYNC_JOB_DUMP, + dumpformat); } else { + if (dumpformat != NULL) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("specifying dumpformat is only supported with " + "memory-only dump")); + goto cleanup; + } ret = qemuMigrationToFile(driver, vm, fd, 0, path, qemuCompressProgramName(compress), false, QEMU_ASYNC_JOB_DUMP); @@ -3513,8 +3535,9 @@ cleanup: return ret; } -static int qemuDomainCoreDump(virDomainPtr dom, +static int qemuDomainCoreDumpWithFormat(virDomainPtr dom, const char *path, + const char *dumpformat, unsigned int flags) { virQEMUDriverPtr driver = dom->conn->privateData; @@ -3531,7 +3554,7 @@ static int qemuDomainCoreDump(virDomainPtr dom, if (!(vm = qemuDomObjFromDomain(dom))) return -1; - if (virDomainCoreDumpEnsureACL(dom->conn, vm->def) < 0) + if (virDomainCoreDumpWithFormatEnsureACL(dom->conn, vm->def) < 0) goto cleanup; if (qemuDomainObjBeginAsyncJob(driver, vm, @@ -3563,7 +3586,8 @@ static int qemuDomainCoreDump(virDomainPtr dom, } } - ret = doCoreDump(driver, vm, path, getCompressionType(driver), flags); + ret = doCoreDump(driver, vm, path, getCompressionType(driver), flags, + dumpformat); if (ret < 0) goto endjob; @@ -3617,6 +3641,13 @@ cleanup: return ret; } +static int qemuDomainCoreDump(virDomainPtr dom, + const char *path, + unsigned int flags) +{ + return qemuDomainCoreDumpWithFormat(dom, path, NULL, flags); +} + static char * qemuDomainScreenshot(virDomainPtr dom, virStreamPtr st, @@ -3740,7 +3771,7 @@ static void processWatchdogEvent(virQEMUDriverPtr driver, virDomainObjPtr vm, in flags |= cfg->autoDumpBypassCache ? VIR_DUMP_BYPASS_CACHE: 0; ret = doCoreDump(driver, vm, dumpfile, - getCompressionType(driver), flags); + getCompressionType(driver), flags, NULL); if (ret < 0) virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("Dump failed")); @@ -3804,7 +3835,7 @@ doCoreDumpToAutoDumpPath(virQEMUDriverPtr driver, flags |= cfg->autoDumpBypassCache ? VIR_DUMP_BYPASS_CACHE: 0; ret = doCoreDump(driver, vm, dumpfile, - getCompressionType(driver), flags); + getCompressionType(driver), flags, NULL); if (ret < 0) virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("Dump failed")); @@ -16625,6 +16656,7 @@ static virDriver qemuDriver = { .domainSaveImageGetXMLDesc = qemuDomainSaveImageGetXMLDesc, /* 0.9.4 */ .domainSaveImageDefineXML = qemuDomainSaveImageDefineXML, /* 0.9.4 */ .domainCoreDump = qemuDomainCoreDump, /* 0.7.0 */ + .domainCoreDumpWithFormat = qemuDomainCoreDumpWithFormat, /* 1.2.3 */ .domainScreenshot = qemuDomainScreenshot, /* 0.9.2 */ .domainSetVcpus = qemuDomainSetVcpus, /* 0.4.4 */ .domainSetVcpusFlags = qemuDomainSetVcpusFlags, /* 0.8.5 */ diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 8104104..78b0634 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2366,10 +2366,10 @@ int qemuMonitorGetDumpGuestMemoryCapability(qemuMonitorPtr mon, } int -qemuMonitorDumpToFd(qemuMonitorPtr mon, int fd) +qemuMonitorDumpToFd(qemuMonitorPtr mon, int fd, const char *dumpformat) { int ret; - VIR_DEBUG("mon=%p fd=%d", mon, fd); + VIR_DEBUG("mon=%p fd=%d dumpformat=%s", mon, fd, dumpformat); if (!mon) { virReportError(VIR_ERR_INVALID_ARG, "%s", @@ -2389,7 +2389,7 @@ qemuMonitorDumpToFd(qemuMonitorPtr mon, int fd) if (qemuMonitorSendFileHandle(mon, "dump", fd) < 0) return -1; - ret = qemuMonitorJSONDump(mon, "fd:dump"); + ret = qemuMonitorJSONDump(mon, "fd:dump", dumpformat); if (ret < 0) { if (qemuMonitorCloseFileHandle(mon, "dump") < 0) diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 00a6554..603a9f8 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -498,7 +498,8 @@ int qemuMonitorGetDumpGuestMemoryCapability(qemuMonitorPtr mon, const char *capability); int qemuMonitorDumpToFd(qemuMonitorPtr mon, - int fd); + int fd, + const char *dumpformat); int qemuMonitorGraphicsRelocate(qemuMonitorPtr mon, int type, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 2cf706c..ecbcb77 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -2701,16 +2701,27 @@ cleanup: int qemuMonitorJSONDump(qemuMonitorPtr mon, - const char *protocol) + const char *protocol, + const char *dumpformat) { int ret; virJSONValuePtr cmd = NULL; virJSONValuePtr reply = NULL; - cmd = qemuMonitorJSONMakeCommand("dump-guest-memory", - "b:paging", false, - "s:protocol", protocol, - NULL); + /* when dumpformat is not NULL, "format":"xxx" is added to the command */ + if (dumpformat) { + cmd = qemuMonitorJSONMakeCommand("dump-guest-memory", + "b:paging", false, + "s:protocol", protocol, + "s:format", dumpformat, + NULL); + } else { + cmd = qemuMonitorJSONMakeCommand("dump-guest-memory", + "b:paging", false, + "s:protocol", protocol, + NULL); + } + if (!cmd) return -1; diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 37e9456..f0a53de 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -151,7 +151,8 @@ int qemuMonitorJSONGetDumpGuestMemoryCapability(qemuMonitorPtr mon, const char *capability); int qemuMonitorJSONDump(qemuMonitorPtr mon, - const char *protocol); + const char *protocol, + const char *memory_dump_format); int qemuMonitorJSONGraphicsRelocate(qemuMonitorPtr mon, int type, diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c index d7da5a8..8e3d0e4 100644 --- a/tests/qemumonitorjsontest.c +++ b/tests/qemumonitorjsontest.c @@ -1154,7 +1154,7 @@ GEN_TEST_FUNC(qemuMonitorJSONSetMigrationDowntime, 1) GEN_TEST_FUNC(qemuMonitorJSONMigrate, QEMU_MONITOR_MIGRATE_BACKGROUND | QEMU_MONITOR_MIGRATE_NON_SHARED_DISK | QEMU_MONITOR_MIGRATE_NON_SHARED_INC, "tcp:localhost:12345") -GEN_TEST_FUNC(qemuMonitorJSONDump, "dummy_protocol") +GEN_TEST_FUNC(qemuMonitorJSONDump, "dummy_protocol", "dummy_dumpformat") GEN_TEST_FUNC(qemuMonitorJSONGraphicsRelocate, VIR_DOMAIN_GRAPHICS_TYPE_SPICE, "localhost", 12345, 12346, NULL) GEN_TEST_FUNC(qemuMonitorJSONAddNetdev, "some_dummy_netdevstr") -- 1.8.5.3

This patch adds "[--dump-format] <string>" to "virsh dump --memory-only", which is changed to use the new virDomainCoreDumpWithFormat API. And "--compress" is also added as an alias for "--dump-format kdump-zlib". Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com> --- tools/virsh-domain.c | 30 +++++++++++++++++++++++++++--- tools/virsh.pod | 6 ++++++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 1d3c5f0..172d659 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -4486,6 +4486,14 @@ static const vshCmdOptDef opts_dump[] = { .type = VSH_OT_BOOL, .help = N_("dump domain's memory only") }, + {.name = "compress", + .type = VSH_OT_ALIAS, + .help = "dump-format=kdump-zlib", + }, + {.name = "dump-format", + .type = VSH_OT_DATA, + .help = N_("specify the format of memory-only dump") + }, {.name = NULL} }; @@ -4501,6 +4509,7 @@ doDump(void *opaque) const char *name = NULL; const char *to = NULL; unsigned int flags = 0; + const char *dumpformat; sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); @@ -4524,9 +4533,24 @@ doDump(void *opaque) if (vshCommandOptBool(cmd, "memory-only")) flags |= VIR_DUMP_MEMORY_ONLY; - if (virDomainCoreDump(dom, to, flags) < 0) { - vshError(ctl, _("Failed to core dump domain %s to %s"), name, to); - goto out; + if (vshCommandOptBool(cmd, "dump-format")) { + if (!(flags & VIR_DUMP_MEMORY_ONLY)) { + vshError(ctl, "%s", + _("--dump-format only works with --memory-only")); + goto out; + } + + ignore_value(vshCommandOptString(cmd, "dump-format", &dumpformat)); + + if (virDomainCoreDumpWithFormat(dom, to, dumpformat, flags) < 0) { + vshError(ctl, _("Failed to core dump domain %s to %s"), name, to); + goto out; + } + } else { + if (virDomainCoreDump(dom, to, flags) < 0) { + vshError(ctl, _("Failed to core dump domain %s to %s"), name, to); + goto out; + } } ret = '0'; diff --git a/tools/virsh.pod b/tools/virsh.pod index cafbb9a..e4b84f6 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -995,6 +995,7 @@ I<format> argument may be B<xen-xm> or B<xen-sxpr>. =item B<dump> I<domain> I<corefilepath> [I<--bypass-cache>] { [I<--live>] | [I<--crash>] | [I<--reset>] } [I<--verbose>] [I<--memory-only>] +[I<--dumpformat> I<string>] Dumps the core of a domain to a file for analysis. If I<--live> is specified, the domain continues to run until the core @@ -1008,6 +1009,11 @@ cache, although this may slow down the operation. If I<--memory-only> is specified, the file is elf file, and will only include domain's memory and cpu common register value. It is very useful if the domain uses host devices directly. +I<--dump-format> I<string> is used to specify the format of 'memory-only' +dump, and I<string> can be one of them: elf, kdump-zlib(kdump-compressed +format with zlib-compressed), kdump-lzo(kdump-compressed format with +lzo-compressed), kdump-snappy(kdump-compressed format with snappy-compressed) +I<--compress> is an alias for I<--dump-format> I<kdump-zlib>. The progress may be monitored using B<domjobinfo> virsh command and canceled with B<domjobabort> command (sent by another virsh instance). Another option -- 1.8.5.3
participants (2)
-
Daniel P. Berrange
-
qiaonuohan@cn.fujitsu.com