--memory-only option is introduced without compression supported. Therefore, this is a freature regression of virsh dump. Now qemu has support dumping memory in kdump-compressed format. This patch is adding new virDomainMemoryDump API, so that the format in which qemu dump domain's memory can be specified. Signed-off-by: Qiao Nuohan <qiaonuohan@xxxxxxxxxxxxxx>_ --- include/libvirt/libvirt.h.in | 21 ++++++++++ src/access/viraccessperm.c | 2 +- src/access/viraccessperm.h | 6 +++ src/driver.h | 7 ++++ src/libvirt.c | 95 ++++++++++++++++++++++++++++++++++++++++++++ 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 | 17 +++++++- 10 files changed, 172 insertions(+), 4 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 295d551..ab6efca 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -1180,6 +1180,19 @@ typedef enum { VIR_DUMP_MEMORY_ONLY = (1 << 4), /* use dump-guest-memory */ } virDomainCoreDumpFlags; +/* Domain memory dump's format */ +typedef enum { + VIR_MEMORY_DUMP_COMPRESS_ZLIB = 1, /* dump guest memory in + kdump-compressed format, with + zlib-compressed */ + VIR_MEMORY_DUMP_COMPRESS_LZO = 2, /* dump guest memory in + kdump-compressed format, with + lzo-compressed */ + VIR_MEMORY_DUMP_COMPRESS_SNAPPY = 3, /* dump guest memory in + kdump-compressed format, with + snappy-compressed */ +} virMemoryDumpFormat; + /* Domain migration flags. */ typedef enum { VIR_MIGRATE_LIVE = (1 << 0), /* live migration */ @@ -1731,6 +1744,14 @@ int virDomainCoreDump (virDomainPtr domain, unsigned int flags); /* + * Domain core dump + */ +int virDomainMemoryDump (virDomainPtr domain, + const char *to, + unsigned int flags, + unsigned int dumpformat); + +/* * Screenshot of current domain console */ char * virDomainScreenshot (virDomainPtr domain, diff --git a/src/access/viraccessperm.c b/src/access/viraccessperm.c index d517c66..af4f05e 100644 --- a/src/access/viraccessperm.c +++ b/src/access/viraccessperm.c @@ -42,7 +42,7 @@ VIR_ENUM_IMPL(virAccessPermDomain, "init_control", "inject_nmi", "send_input", "send_signal", "fs_trim", "block_read", "block_write", "mem_read", "open_graphics", "open_device", "screenshot", - "open_namespace"); + "open_namespace", "memory_dump"); VIR_ENUM_IMPL(virAccessPermInterface, VIR_ACCESS_PERM_INTERFACE_LAST, diff --git a/src/access/viraccessperm.h b/src/access/viraccessperm.h index 6d14f05..2537fbf 100644 --- a/src/access/viraccessperm.h +++ b/src/access/viraccessperm.h @@ -205,6 +205,12 @@ typedef enum { VIR_ACCESS_PERM_DOMAIN_CORE_DUMP, /* Dump guest core */ /** + * @desc: Dump domain's memory only + * @message: Dumping domain's memory requires authorization + */ + VIR_ACCESS_PERM_DOMAIN_MEMORY_DUMP, /* Dump guest's memory only */ + + /** * @desc: Use domain power management * @message: Using domain power management requires authoriation */ diff --git a/src/driver.h b/src/driver.h index fbfaac4..7c001e6 100644 --- a/src/driver.h +++ b/src/driver.h @@ -306,6 +306,12 @@ typedef int const char *to, unsigned int flags); +typedef int +(*virDrvDomainMemoryDump)(virDomainPtr domain, + const char *to, + unsigned int flags, + unsigned int dumpformat); + typedef char * (*virDrvDomainScreenshot)(virDomainPtr domain, virStreamPtr stream, @@ -1200,6 +1206,7 @@ struct _virDriver { virDrvDomainSaveImageGetXMLDesc domainSaveImageGetXMLDesc; virDrvDomainSaveImageDefineXML domainSaveImageDefineXML; virDrvDomainCoreDump domainCoreDump; + virDrvDomainMemoryDump domainMemoryDump; virDrvDomainScreenshot domainScreenshot; virDrvDomainSetVcpus domainSetVcpus; virDrvDomainSetVcpusFlags domainSetVcpusFlags; diff --git a/src/libvirt.c b/src/libvirt.c index dcf6b53..ec106a6 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -2999,6 +2999,101 @@ error: return -1; } +/** + * virDomainMemoryDump: + * @domain: a domain object + * @to: path for the core file + * @flags: bitwise-OR of virDomainCoreDumpFlags + * @dumpformat: format of domain memory's dump + * + * This method will only dump the memory of a domain on a given file for + * analysis, so @flag must includes VIR_DUMP_MEMORY_ONLY. + * + * 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. + * + * when @flags includes VIR_DUMP_MEMORY_ONLY and dumpformat is set, libvirt + * will ask qemu dump domain's memory in kdump-compressed format. + * + * 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 +virDomainMemoryDump(virDomainPtr domain, const char *to, unsigned int flags, + unsigned int dumpformat) +{ + virConnectPtr conn; + + VIR_DOMAIN_DEBUG(domain, "to=%s, flags=%x", to, flags); + + virResetLastError(); + + virCheckDomainReturn(domain, -1); + conn = domain->conn; + + virCheckReadOnlyGoto(conn->flags, error); + virCheckNonNullArgGoto(to, error); + + if (!(flags & VIR_DUMP_MEMORY_ONLY)) { + virReportInvalidArg(flags, "%s", + _("memory-only flag is needed to dump domain's memory only")); + 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->domainMemoryDump) { + 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->domainMemoryDump(domain, absolute_to, flags, + dumpformat); + + 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..7135242 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: + virDomainMemoryDump; +} 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..c5772ed 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 */ + .domainMemoryDump = remoteDomainMemoryDump, /* 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..680456f 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_memory_dump_args { + remote_nonnull_domain dom; + remote_nonnull_string to; + unsigned int flags; + unsigned int dumpformat; +}; + 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:memory_dump + */ + REMOTE_PROC_DOMAIN_MEMORY_DUMP = 334 }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 5636d55..01a9dbe 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_memory_dump_args { + remote_nonnull_domain dom; + remote_nonnull_string to; + u_int flags; + u_int dumpformat; +}; 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_MEMORY_DUMP = 334, }; diff --git a/src/test/test_driver.c b/src/test/test_driver.c index b724f82..cf93f97 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, +static int testDomainMemoryDump(virDomainPtr domain, const char *to, - unsigned int flags) + unsigned int flags, + unsigned int dumpformat) { testConnPtr privconn = domain->conn->privateData; int fd = -1; @@ -2479,6 +2480,12 @@ static int testDomainCoreDump(virDomainPtr domain, } } + if (dumpformat > VIR_MEMORY_DUMP_COMPRESS_SNAPPY) { + virReportSystemError(errno, + _("invalid value of dumpformat: %d"), dumpformat); + goto cleanup; + } + ret = 0; cleanup: VIR_FORCE_CLOSE(fd); @@ -2490,6 +2497,12 @@ cleanup: return ret; } +static int testDomainCoreDump(virDomainPtr domain, + const char *to, + unsigned int flags) { + return testDomainMemoryDump(domain, to, flags, 0); +} + static char *testDomainGetOSType(virDomainPtr dom ATTRIBUTE_UNUSED) { char *ret; -- 1.8.5.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list