[libvirt] [PATCH v8 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 v7 to v8: 1. add test for qemuMonitorGetDumpGuestMemoryCapability 2. fix a bug when dumping a elf core with the an older version of qemu Changes from v6 to v7: 1. revert changing dumpformat of virDomainCoreDumpWithFormat back to an enum 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 | 31 ++++++++++++++ src/driver.h | 7 ++++ src/libvirt.c | 98 ++++++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 5 +++ src/qemu/qemu_driver.c | 75 ++++++++++++++++++++++++++++----- src/qemu/qemu_monitor.c | 27 ++++++++++-- src/qemu/qemu_monitor.h | 6 ++- src/qemu/qemu_monitor_json.c | 85 +++++++++++++++++++++++++++++++++++--- 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 | 22 ++++++++-- tests/qemumonitorjsontest.c | 45 +++++++++++++++++++- tools/virsh-domain.c | 47 +++++++++++++++++++-- tools/virsh.pod | 6 +++ 16 files changed, 454 insertions(+), 29 deletions(-) -- 1.8.5.3

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 ++ tests/qemumonitorjsontest.c | 43 +++++++++++++++++++++++++++++ 5 files changed, 135 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); diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c index d7da5a8..d21e1ce 100644 --- a/tests/qemumonitorjsontest.c +++ b/tests/qemumonitorjsontest.c @@ -1959,6 +1959,48 @@ cleanup: return ret; } +static int +testQemuMonitorJSONqemuMonitorJSONGetDumpGuestMemoryCapability(const void *data) +{ + virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data; + qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt); + int ret = -1; + int cap; + const char *reply = + "{" + " \"return\": {" + " \"formats\": [" + " \"elf\"," + " \"kdump-zlib\"," + " \"kdump-lzo\"," + " \"kdump-snappy\"" + " ]" + " }," + " \"id\": \"libvirt-9\"" + "}"; + + if (!test) + return -1; + + if (qemuMonitorTestAddItem(test, "query-dump-guest-memory-capability", + reply) < 0) + goto cleanup; + + cap = qemuMonitorJSONGetDumpGuestMemoryCapability( + qemuMonitorTestGetMonitor(test), "elf"); + + if (cap != 1) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "Unexpected capability: %d, expecting 1", + cap); + goto cleanup; + } + + ret = 0; +cleanup: + qemuMonitorTestFree(test); + return ret; +} struct testCPUData { const char *name; @@ -2187,6 +2229,7 @@ mymain(void) DO_TEST(qemuMonitorJSONGetCPUInfo); DO_TEST(qemuMonitorJSONGetVirtType); DO_TEST(qemuMonitorJSONSendKey); + DO_TEST(qemuMonitorJSONGetDumpGuestMemoryCapability); DO_TEST_CPU_DATA("host"); DO_TEST_CPU_DATA("full"); -- 1.8.5.3

On Fri, Mar 21, 2014 at 07:03:31AM +0000, qiaonuohan@cn.fujitsu.com wrote:
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 ++ tests/qemumonitorjsontest.c | 43 +++++++++++++++++++++++++++++ 5 files changed, 135 insertions(+)
ACK 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 makes qemu driver support virDomainCoreDumpWithFormat API. Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com> --- src/qemu/qemu_driver.c | 75 +++++++++++++++++++++++++++++++++++++------- src/qemu/qemu_monitor.c | 6 ++-- src/qemu/qemu_monitor.h | 3 +- src/qemu/qemu_monitor_json.c | 20 +++++++++--- src/qemu/qemu_monitor_json.h | 3 +- tests/qemumonitorjsontest.c | 2 +- 6 files changed, 87 insertions(+), 22 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 9aad2dc..b732bda 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -2676,6 +2676,13 @@ VIR_ENUM_IMPL(qemuSaveCompression, QEMU_SAVE_FORMAT_LAST, "xz", "lzop") +VIR_ENUM_DECL(qemuDumpFormat) +VIR_ENUM_IMPL(qemuDumpFormat, VIR_DOMAIN_CORE_DUMP_FORMAT_LAST, + "elf", + "kdump-zlib", + "kdump-lzo", + "kdump-snappy") + typedef struct _virQEMUSaveHeader virQEMUSaveHeader; typedef virQEMUSaveHeader *virQEMUSaveHeaderPtr; struct _virQEMUSaveHeader { @@ -3389,7 +3396,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 +3417,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,13 +3441,15 @@ doCoreDump(virQEMUDriverPtr driver, virDomainObjPtr vm, const char *path, virQEMUSaveFormat compress, - unsigned int dump_flags) + unsigned int dump_flags, + unsigned int dumpformat) { int fd = -1; int ret = -1; virFileWrapperFdPtr wrapperFd = NULL; int directFlag = 0; unsigned int flags = VIR_FILE_WRAPPER_NON_BLOCKING; + const char *memory_dump_format = NULL; /* Create an empty file with appropriate ownership. */ if (dump_flags & VIR_DUMP_BYPASS_CACHE) { @@ -3450,8 +3473,25 @@ doCoreDump(virQEMUDriverPtr driver, goto cleanup; if (dump_flags & VIR_DUMP_MEMORY_ONLY) { - ret = qemuDumpToFd(driver, vm, fd, QEMU_ASYNC_JOB_DUMP); + if (!(memory_dump_format = qemuDumpFormatTypeToString(dumpformat))) { + virReportError(VIR_ERR_INVALID_ARG, + _("unknown dumpformat '%d'"), dumpformat); + goto cleanup; + } + + /* qemu dumps in "elf" without dumpformat set */ + if (STREQ(memory_dump_format, "elf")) + memory_dump_format = NULL; + + ret = qemuDumpToFd(driver, vm, fd, QEMU_ASYNC_JOB_DUMP, + memory_dump_format); } else { + if (dumpformat != VIR_DOMAIN_CORE_DUMP_FORMAT_RAW) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("kdump-compressed format is only supported with " + "memory-only dump")); + goto cleanup; + } ret = qemuMigrationToFile(driver, vm, fd, 0, path, qemuCompressProgramName(compress), false, QEMU_ASYNC_JOB_DUMP); @@ -3513,9 +3553,10 @@ cleanup: return ret; } -static int qemuDomainCoreDump(virDomainPtr dom, - const char *path, - unsigned int flags) +static int qemuDomainCoreDumpWithFormat(virDomainPtr dom, + const char *path, + unsigned int dumpformat, + unsigned int flags) { virQEMUDriverPtr driver = dom->conn->privateData; virDomainObjPtr vm; @@ -3531,7 +3572,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 +3604,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 +3659,14 @@ cleanup: return ret; } +static int qemuDomainCoreDump(virDomainPtr dom, + const char *path, + unsigned int flags) +{ + return qemuDomainCoreDumpWithFormat(dom, path, + VIR_DOMAIN_CORE_DUMP_FORMAT_RAW, flags); +} + static char * qemuDomainScreenshot(virDomainPtr dom, virStreamPtr st, @@ -3740,7 +3790,8 @@ 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, + VIR_DOMAIN_CORE_DUMP_FORMAT_RAW); if (ret < 0) virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("Dump failed")); @@ -3804,7 +3855,8 @@ doCoreDumpToAutoDumpPath(virQEMUDriverPtr driver, flags |= cfg->autoDumpBypassCache ? VIR_DUMP_BYPASS_CACHE: 0; ret = doCoreDump(driver, vm, dumpfile, - getCompressionType(driver), flags); + getCompressionType(driver), flags, + VIR_DOMAIN_CORE_DUMP_FORMAT_RAW); if (ret < 0) virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("Dump failed")); @@ -16625,6 +16677,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..c613e27 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -2701,16 +2701,26 @@ 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); + 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..26a9f1e 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 *dumpformat); int qemuMonitorJSONGraphicsRelocate(qemuMonitorPtr mon, int type, diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c index d21e1ce..6b48296 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_memory_dump_format") GEN_TEST_FUNC(qemuMonitorJSONGraphicsRelocate, VIR_DOMAIN_GRAPHICS_TYPE_SPICE, "localhost", 12345, 12346, NULL) GEN_TEST_FUNC(qemuMonitorJSONAddNetdev, "some_dummy_netdevstr") -- 1.8.5.3

On Fri, Mar 21, 2014 at 07:03:31AM +0000, qiaonuohan@cn.fujitsu.com wrote:
This patch makes qemu driver support virDomainCoreDumpWithFormat API.
Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com> --- src/qemu/qemu_driver.c | 75 +++++++++++++++++++++++++++++++++++++------- src/qemu/qemu_monitor.c | 6 ++-- src/qemu/qemu_monitor.h | 3 +- src/qemu/qemu_monitor_json.c | 20 +++++++++--- src/qemu/qemu_monitor_json.h | 3 +- tests/qemumonitorjsontest.c | 2 +- 6 files changed, 87 insertions(+), 22 deletions(-)
ACK 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 :|

--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 | 31 ++++++++++++++ src/driver.h | 7 ++++ src/libvirt.c | 98 ++++++++++++++++++++++++++++++++++++++++++++ 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 | 22 ++++++++-- 8 files changed, 182 insertions(+), 4 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 295d551..41cd28c 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -1180,6 +1180,29 @@ typedef enum { VIR_DUMP_MEMORY_ONLY = (1 << 4), /* use dump-guest-memory */ } virDomainCoreDumpFlags; +/** + * virDomainCoreDumpFormat: + * + * Values for specifying different formats of domain core dumps. + */ +typedef enum { + VIR_DOMAIN_CORE_DUMP_FORMAT_RAW, /* dump guest memory in raw format */ + VIR_DOMAIN_CORE_DUMP_FORMAT_KDUMP_ZLIB, /* kdump-compressed format, with + * zlib compression */ + VIR_DOMAIN_CORE_DUMP_FORMAT_KDUMP_LZO, /* kdump-compressed format, with + * lzo compression */ + VIR_DOMAIN_CORE_DUMP_FORMAT_KDUMP_SNAPPY, /* kdump-compressed format, with + * snappy compression */ +#ifdef VIR_ENUM_SENTINELS + VIR_DOMAIN_CORE_DUMP_FORMAT_LAST + /* + * NB: this enum value will increase over time as new events are + * added to the libvirt API. It reflects the last state supported + * by this version of the libvirt API. + */ +#endif +} virDomainCoreDumpFormat; + /* Domain migration flags. */ typedef enum { VIR_MIGRATE_LIVE = (1 << 0), /* live migration */ @@ -1731,6 +1754,14 @@ int virDomainCoreDump (virDomainPtr domain, unsigned int flags); /* + * Domain core dump with format specified + */ +int virDomainCoreDumpWithFormat (virDomainPtr domain, + const char *to, + unsigned int 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..d613f64 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, + unsigned int 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..6cfa2ce 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -2997,6 +2997,104 @@ 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 kdump-compressed format. + * + * 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, unsigned int + dumpformat, unsigned int flags) +{ + virConnectPtr conn; + + VIR_DOMAIN_DEBUG(domain, "to=%s, dumpformat=%u, flags=%x", + to, dumpformat, flags); + + virResetLastError(); + + virCheckDomainReturn(domain, -1); + conn = domain->conn; + + virCheckReadOnlyGoto(conn->flags, error); + virCheckNonNullArgGoto(to, error); + + if (dumpformat >= VIR_DOMAIN_CORE_DUMP_FORMAT_LAST) { + virReportInvalidArg(flags, _("dumpformat '%d' is not supported"), + dumpformat); + goto 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..6c445cc 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; + unsigned int 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..456d0da 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; + u_int 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..96ec538 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, + unsigned int 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 non-raw formats in test driver */ + if (dumpformat != VIR_DOMAIN_CORE_DUMP_FORMAT_RAW) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("kdump-compressed format is not supported here")); + goto cleanup; + } + if (flags & VIR_DUMP_CRASH) { testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_CRASHED); event = virDomainEventLifecycleNewFromObj(privdom, @@ -2490,6 +2498,13 @@ cleanup: return ret; } +static int testDomainCoreDump(virDomainPtr domain, + const char *to, + unsigned int flags) { + return testDomainCoreDumpWithFormat(domain, to, + VIR_DOMAIN_CORE_DUMP_FORMAT_RAW, flags); +} + static char *testDomainGetOSType(virDomainPtr dom ATTRIBUTE_UNUSED) { char *ret; @@ -7359,6 +7374,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 Fri, Mar 21, 2014 at 07:03:31AM +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>
ACK 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 :|

On 03/21/2014 01:03 AM, 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>
Your From: spelling (qiaonuohan@cn.fujitsu.com) does not match your Signed-off-by: spelling (Qiao Nuohan). If 'git am' were to take your email as-is, then 'git shortlog' would show your email instead of your name as the author. You should consider running git config --global user.name "Qiao Nuohan" and/or git config --global sendemail.from \ "Qiao Nuohan <qiaonuohan@cn.fujitsu.com> so that in the future, 'git send-email' will make your From: match your S-o-B. On 03/21/2014 08:54 AM, Daniel P. Berrange wrote:
ACK
Unfortunately, I tried to apply your patches, but 'git am' did not like them: $ git am -3 *API.eml Applying: add new virDomainCoreDumpWithFormat API Using index info to reconstruct a base tree... M include/libvirt/libvirt.h.in M src/driver.h M src/libvirt.c M src/remote/remote_driver.c M src/test/test_driver.c <stdin>:20: trailing whitespace. /** <stdin>:21: trailing whitespace. * virDomainCoreDumpFormat: <stdin>:22: trailing whitespace. * <stdin>:23: trailing whitespace. * Values for specifying different formats of domain core dumps. <stdin>:24: trailing whitespace. */ error: patch failed: include/libvirt/libvirt.h.in:1180 error: include/libvirt/libvirt.h.in: patch does not apply error: patch failed: src/driver.h:306 error: src/driver.h: patch does not apply error: patch failed: src/libvirt.c:2997 error: src/libvirt.c: patch does not apply error: patch failed: src/libvirt_public.syms:645 error: src/libvirt_public.syms: patch does not apply error: patch failed: src/remote/remote_driver.c:7516 error: src/remote/remote_driver.c: patch does not apply error: patch failed: src/remote/remote_protocol.x:904 error: src/remote/remote_protocol.x: patch does not apply error: patch failed: src/remote_protocol-structs:557 error: src/remote_protocol-structs: patch does not apply error: patch failed: src/test/test_driver.c:2427 error: src/test/test_driver.c: patch does not apply Did you hand edit your patch? It does not apply to blobs recorded in its index. Cannot fall back to three-way merge. Patch failed at 0001 add new virDomainCoreDumpWithFormat API The copy of the patch that failed is found in: /home/eblake/libvirt/.git/rebase-apply/patch Can you please rebase and repost them in a way that is not whitespace munged by your mailer? -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

At 03/22/2014 06:22 AM, Eric Blake Wrote:
On 03/21/2014 01:03 AM, 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>
Your From: spelling (qiaonuohan@cn.fujitsu.com) does not match your Signed-off-by: spelling (Qiao Nuohan). If 'git am' were to take your email as-is, then 'git shortlog' would show your email instead of your name as the author. You should consider running git config --global user.name "Qiao Nuohan" and/or git config --global sendemail.from \ "Qiao Nuohan <qiaonuohan@cn.fujitsu.com> so that in the future, 'git send-email' will make your From: match your S-o-B.
On 03/21/2014 08:54 AM, Daniel P. Berrange wrote:
ACK
Unfortunately, I tried to apply your patches, but 'git am' did not like them:
$ git am -3 *API.eml Applying: add new virDomainCoreDumpWithFormat API Using index info to reconstruct a base tree... M include/libvirt/libvirt.h.in M src/driver.h M src/libvirt.c M src/remote/remote_driver.c M src/test/test_driver.c <stdin>:20: trailing whitespace. /** <stdin>:21: trailing whitespace. * virDomainCoreDumpFormat: <stdin>:22: trailing whitespace. * <stdin>:23: trailing whitespace. * Values for specifying different formats of domain core dumps. <stdin>:24: trailing whitespace. */ error: patch failed: include/libvirt/libvirt.h.in:1180 error: include/libvirt/libvirt.h.in: patch does not apply error: patch failed: src/driver.h:306 error: src/driver.h: patch does not apply error: patch failed: src/libvirt.c:2997 error: src/libvirt.c: patch does not apply error: patch failed: src/libvirt_public.syms:645 error: src/libvirt_public.syms: patch does not apply error: patch failed: src/remote/remote_driver.c:7516 error: src/remote/remote_driver.c: patch does not apply error: patch failed: src/remote/remote_protocol.x:904 error: src/remote/remote_protocol.x: patch does not apply error: patch failed: src/remote_protocol-structs:557 error: src/remote_protocol-structs: patch does not apply error: patch failed: src/test/test_driver.c:2427 error: src/test/test_driver.c: patch does not apply Did you hand edit your patch? It does not apply to blobs recorded in its index. Cannot fall back to three-way merge. Patch failed at 0001 add new virDomainCoreDumpWithFormat API The copy of the patch that failed is found in: /home/eblake/libvirt/.git/rebase-apply/patch
Can you please rebase and repost them in a way that is not whitespace munged by your mailer?
I guess it is our new mailserver problem. I will resend them via old mailserver Thanks Wen Congyang
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

This patch adds "[--format] <string>" to "virsh dump --memory-only", which is changed to use the new virDomainCoreDumpWithFormat API. And "--compress" is added as an alias for "--format kdump-zlib". Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com> --- tools/virsh-domain.c | 47 ++++++++++++++++++++++++++++++++++++++++++++--- tools/virsh.pod | 6 ++++++ 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 1d3c5f0..6458752 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 = "format=kdump-zlib", + }, + {.name = "format", + .type = VSH_OT_DATA, + .help = N_("specify the format of memory-only dump") + }, {.name = NULL} }; @@ -4501,6 +4509,8 @@ doDump(void *opaque) const char *name = NULL; const char *to = NULL; unsigned int flags = 0; + const char *format = NULL; + unsigned int dumpformat = VIR_DOMAIN_CORE_DUMP_FORMAT_RAW; sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); @@ -4524,9 +4534,40 @@ 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, "format")) { + if (!(flags & VIR_DUMP_MEMORY_ONLY)) { + vshError(ctl, "%s", _("--format only work with --memory-only")); + goto out; + } + + if (vshCommandOptString(cmd, "format", &format)) { + if (STREQ(format, "kdump-zlib")) + dumpformat = VIR_DOMAIN_CORE_DUMP_FORMAT_KDUMP_ZLIB; + else if (STREQ(format, "kdump-lzo")) + dumpformat = VIR_DOMAIN_CORE_DUMP_FORMAT_KDUMP_LZO; + else if (STREQ(format, "kdump-snappy")) + dumpformat = VIR_DOMAIN_CORE_DUMP_FORMAT_KDUMP_SNAPPY; + else if (STREQ(format, "elf")) + dumpformat = VIR_DOMAIN_CORE_DUMP_FORMAT_RAW; + else { + vshError(ctl, _("format '%s' is not supported, expecting " + "'kdump-zlib', 'kdump-lzo', 'kdump-snappy' " + "or 'elf'."), format); + goto out; + } + } + } + + if (dumpformat != VIR_DOMAIN_CORE_DUMP_FORMAT_RAW) { + 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..3ce8c6a 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<--format> 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<--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<--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

On Fri, Mar 21, 2014 at 07:03:31AM +0000, qiaonuohan@cn.fujitsu.com wrote:
This patch adds "[--format] <string>" to "virsh dump --memory-only", which is changed to use the new virDomainCoreDumpWithFormat API. And "--compress" is added as an alias for "--format kdump-zlib".
Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com> --- tools/virsh-domain.c | 47 ++++++++++++++++++++++++++++++++++++++++++++--- tools/virsh.pod | 6 ++++++ 2 files changed, 50 insertions(+), 3 deletions(-)
ACK 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 :|
participants (4)
-
Daniel P. Berrange
-
Eric Blake
-
qiaonuohan@cn.fujitsu.com
-
Wen Congyang