[libvirt] [PATCH v2 1/2] make qemu dump memory in kdump-compressed format

Qiao Nuohan qiaonuohan at cn.fujitsu.com
Tue Feb 25 09:54:30 UTC 2014


--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 used to add "--compress" and
"[--compression-format] <string>" to "virsh dump --memory-only" and send
dump-guest-memory command to qemu with dump format specified to one of elf,
kdump-zlib, kdump-lzo and kdump-snappy.

Signed-off-by: Qiao Nuohan <qiaonuohan at cn.fujitsu.com>
---
  include/libvirt/libvirt.h.in | 15 ++++++++++++++-
  src/driver.h                 |  3 ++-
  src/libvirt.c                | 10 ++++++++--
  src/qemu/qemu_driver.c       | 30 +++++++++++++++++++++--------
  src/qemu/qemu_monitor.c      |  6 +++---
  src/qemu/qemu_monitor.h      |  3 ++-
  src/qemu/qemu_monitor_json.c |  4 +++-
  src/qemu/qemu_monitor_json.h |  3 ++-
  src/remote/remote_protocol.x |  1 +
  src/test/test_driver.c       | 12 +++++++++++-
  tests/qemumonitorjsontest.c  |  2 +-
  tools/virsh-domain.c         | 45 +++++++++++++++++++++++++++++++++++++++++++-
  12 files changed, 113 insertions(+), 21 deletions(-)

diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 295d551..aae3c49 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -1180,6 +1180,18 @@ typedef enum {
      VIR_DUMP_MEMORY_ONLY  = (1 << 4), /* use dump-guest-memory */
  } virDomainCoreDumpFlags;

+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 */
@@ -1728,7 +1740,8 @@ int 
virDomainManagedSaveRemove(virDomainPtr dom,
   */
  int                     virDomainCoreDump       (virDomainPtr domain,
                                                   const char *to,
-                                                 unsigned int flags);
+                                                 unsigned int flags,
+                                                 const unsigned int 
memory_dump_format);

  /*
   * Screenshot of current domain console
diff --git a/src/driver.h b/src/driver.h
index 5f4cd8d..c228fd0 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -303,7 +303,8 @@ typedef int
  typedef int
  (*virDrvDomainCoreDump)(virDomainPtr domain,
                          const char *to,
-                        unsigned int flags);
+                        unsigned int flags,
+                        const unsigned int memory_dump_format);

  typedef char *
  (*virDrvDomainScreenshot)(virDomainPtr domain,
diff --git a/src/libvirt.c b/src/libvirt.c
index 9cc5b1c..0659baf 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -2916,6 +2916,7 @@ error:
   * @domain: a domain object
   * @to: path for the core file
   * @flags: bitwise-OR of virDomainCoreDumpFlags
+ * @memory_dump_format: format of guest memory's dump
   *
   * 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
@@ -2934,10 +2935,14 @@ error:
   * 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.
   *
+ * when @flags includes VIR_DUMP_MEMORY_ONLY and memory_dump_format is set,
+ * libvirt will ask qemu dump guest's memory in kdump-compressed format.
+ *
   * Returns 0 in case of success and -1 in case of failure.
   */
  int
-virDomainCoreDump(virDomainPtr domain, const char *to, unsigned int flags)
+virDomainCoreDump(virDomainPtr domain, const char *to, unsigned int flags,
+                  const unsigned int memory_dump_format)
  {
      virConnectPtr conn;

@@ -2980,7 +2985,8 @@ virDomainCoreDump(virDomainPtr domain, const char *to, 
unsigned int flags)
              goto error;
          }

-        ret = conn->driver->domainCoreDump(domain, absolute_to, flags);
+        ret = conn->driver->domainCoreDump(domain, absolute_to, flags,
+                                           memory_dump_format);

          VIR_FREE(absolute_to);

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 59e018d..7b6fa43 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -3383,7 +3383,8 @@ cleanup:
  }

  static int qemuDumpToFd(virQEMUDriverPtr driver, virDomainObjPtr vm,
-                        int fd, enum qemuDomainAsyncJob asyncJob)
+                        int fd, enum qemuDomainAsyncJob asyncJob,
+                        const char* dump_format)
  {
      qemuDomainObjPrivatePtr priv = vm->privateData;
      int ret = -1;
@@ -3403,7 +3404,7 @@ static int qemuDumpToFd(virQEMUDriverPtr driver, 
virDomainObjPtr vm,
      if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
          return -1;

-    ret = qemuMonitorDumpToFd(priv->mon, fd);
+    ret = qemuMonitorDumpToFd(priv->mon, fd, dump_format);
      qemuDomainObjExitMonitor(driver, vm);

      return ret;
@@ -3414,13 +3415,15 @@ doCoreDump(virQEMUDriverPtr driver,
             virDomainObjPtr vm,
             const char *path,
             virQEMUSaveFormat compress,
-           unsigned int dump_flags)
+           unsigned int dump_flags,
+           const unsigned int memory_dump_format)
  {
      int fd = -1;
      int ret = -1;
      virFileWrapperFdPtr wrapperFd = NULL;
      int directFlag = 0;
      unsigned int flags = VIR_FILE_WRAPPER_NON_BLOCKING;
+    const char *dump_format;

      /* Create an empty file with appropriate ownership.  */
      if (dump_flags & VIR_DUMP_BYPASS_CACHE) {
@@ -3444,7 +3447,16 @@ 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 == VIR_MEMORY_DUMP_COMPRESS_ZLIB)
+            dump_format = "kdump-zlib";
+        else if (memory_dump_format == VIR_MEMORY_DUMP_COMPRESS_LZO)
+            dump_format = "kdump-lzo";
+        else if (memory_dump_format == VIR_MEMORY_DUMP_COMPRESS_SNAPPY)
+            dump_format = "kdump-snappy";
+        else
+            dump_format = "elf";
+        ret = qemuDumpToFd(driver, vm, fd, QEMU_ASYNC_JOB_DUMP,
+                           dump_format);
      } else {
          ret = qemuMigrationToFile(driver, vm, fd, 0, path,
                                    qemuCompressProgramName(compress), false,
@@ -3509,7 +3521,8 @@ cleanup:

  static int qemuDomainCoreDump(virDomainPtr dom,
                                const char *path,
-                              unsigned int flags)
+                              unsigned int flags,
+                              const unsigned int memory_dump_format)
  {
      virQEMUDriverPtr driver = dom->conn->privateData;
      virDomainObjPtr vm;
@@ -3557,7 +3570,8 @@ static int qemuDomainCoreDump(virDomainPtr dom,
          }
      }

-    ret = doCoreDump(driver, vm, path, getCompressionType(driver), flags);
+    ret = doCoreDump(driver, vm, path, getCompressionType(driver), flags,
+                     memory_dump_format);
      if (ret < 0)
          goto endjob;

@@ -3734,7 +3748,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, 0);
              if (ret < 0)
                  virReportError(VIR_ERR_OPERATION_FAILED,
                                 "%s", _("Dump failed"));
@@ -3798,7 +3812,7 @@ doCoreDumpToAutoDumpPath(virQEMUDriverPtr driver,

      flags |= cfg->autoDumpBypassCache ? VIR_DUMP_BYPASS_CACHE: 0;
      ret = doCoreDump(driver, vm, dumpfile,
-                     getCompressionType(driver), flags);
+                     getCompressionType(driver), flags, 0);
      if (ret < 0)
          virReportError(VIR_ERR_OPERATION_FAILED,
                         "%s", _("Dump failed"));
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index a2769db..2722781 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -2345,10 +2345,10 @@ int qemuMonitorMigrateCancel(qemuMonitorPtr mon)
  }

  int
-qemuMonitorDumpToFd(qemuMonitorPtr mon, int fd)
+qemuMonitorDumpToFd(qemuMonitorPtr mon, int fd, const char *dump_format)
  {
      int ret;
-    VIR_DEBUG("mon=%p fd=%d", mon, fd);
+    VIR_DEBUG("mon=%p fd=%d dump_format=%s", mon, fd, dump_format);

      if (!mon) {
          virReportError(VIR_ERR_INVALID_ARG, "%s",
@@ -2368,7 +2368,7 @@ qemuMonitorDumpToFd(qemuMonitorPtr mon, int fd)
      if (qemuMonitorSendFileHandle(mon, "dump", fd) < 0)
          return -1;

-    ret = qemuMonitorJSONDump(mon, "fd:dump");
+    ret = qemuMonitorJSONDump(mon, "fd:dump", dump_format);

      if (ret < 0) {
          if (qemuMonitorCloseFileHandle(mon, "dump") < 0)
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index eabf000..f2e5763 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -495,7 +495,8 @@ int qemuMonitorMigrateToUnix(qemuMonitorPtr mon,
  int qemuMonitorMigrateCancel(qemuMonitorPtr mon);

  int qemuMonitorDumpToFd(qemuMonitorPtr mon,
-                        int fd);
+                        int fd,
+                        const char *dump_format);

  int qemuMonitorGraphicsRelocate(qemuMonitorPtr mon,
                                  int type,
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 5e825ac..7c9625f 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -2636,7 +2636,8 @@ int qemuMonitorJSONMigrateCancel(qemuMonitorPtr mon)

  int
  qemuMonitorJSONDump(qemuMonitorPtr mon,
-                    const char *protocol)
+                    const char *protocol,
+                    const char *dump_format)
  {
      int ret;
      virJSONValuePtr cmd = NULL;
@@ -2645,6 +2646,7 @@ qemuMonitorJSONDump(qemuMonitorPtr mon,
      cmd = qemuMonitorJSONMakeCommand("dump-guest-memory",
                                       "b:paging", false,
                                       "s:protocol", protocol,
+                                     "s:format", dump_format,
                                       NULL);
      if (!cmd)
          return -1;
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index a93c51e..7691356 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -148,7 +148,8 @@ int qemuMonitorJSONGetSpiceMigrationStatus(qemuMonitorPtr mon,
  int qemuMonitorJSONMigrateCancel(qemuMonitorPtr mon);

  int qemuMonitorJSONDump(qemuMonitorPtr mon,
-                        const char *protocol);
+                        const char *protocol,
+                        const char *dump_format);

  int qemuMonitorJSONGraphicsRelocate(qemuMonitorPtr mon,
                                      int type,
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index f1f2359..cc6f68b 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -902,6 +902,7 @@ struct remote_domain_core_dump_args {
      remote_nonnull_domain dom;
      remote_nonnull_string to;
      unsigned int flags;
+    unsigned int memory_dump_format;
  };

  struct remote_domain_screenshot_args {
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index b724f82..559933f 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -2429,7 +2429,8 @@ testDomainRestore(virConnectPtr conn,

  static int testDomainCoreDump(virDomainPtr domain,
                                const char *to,
-                              unsigned int flags)
+                              unsigned int flags,
+                              const unsigned int memory_dump_format)
  {
      testConnPtr privconn = domain->conn->privateData;
      int fd = -1;
@@ -2479,6 +2480,15 @@ static int testDomainCoreDump(virDomainPtr domain,
          }
      }

+    if (!(flags & VIR_DUMP_MEMORY_ONLY) && (memory_dump_format ==
+        VIR_MEMORY_DUMP_COMPRESS_ZLIB || memory_dump_format ==
+        VIR_MEMORY_DUMP_COMPRESS_LZO || memory_dump_format ==
+        VIR_MEMORY_DUMP_COMPRESS_SNAPPY)) {
+        virReportSystemError(errno,
+                             _("%s"), "memory_dump_format is available when "
+                               "VIR_DUMP_MEMORY_ONLY is set");
+    }
+
      ret = 0;
  cleanup:
      VIR_FORCE_CLOSE(fd);
diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c
index d7da5a8..c02016f 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_dump_format")
  GEN_TEST_FUNC(qemuMonitorJSONGraphicsRelocate, VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
                "localhost", 12345, 12346, NULL)
  GEN_TEST_FUNC(qemuMonitorJSONAddNetdev, "some_dummy_netdevstr")
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index c3db94c..ba17d10 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -4519,6 +4519,14 @@ static const vshCmdOptDef opts_dump[] = {
       .type = VSH_OT_BOOL,
       .help = N_("dump domain's memory only")
      },
+    {.name = "compress",
+     .type = VSH_OT_BOOL,
+     .help = N_("make qemu dump domain's memory in kdump-compressed format")
+    },
+    {.name = "compression-format",
+     .type = VSH_OT_DATA,
+     .help = N_("specify the compression format of kdump-compressed format")
+    },
      {.name = NULL}
  };

@@ -4533,6 +4541,9 @@ doDump(void *opaque)
      sigset_t sigmask, oldsigmask;
      const char *name = NULL;
      const char *to = NULL;
+    bool optCompress;
+    const char *compression_format = NULL;
+    unsigned int memory_dump_format = 0;
      unsigned int flags = 0;

      sigemptyset(&sigmask);
@@ -4557,7 +4568,39 @@ doDump(void *opaque)
      if (vshCommandOptBool(cmd, "memory-only"))
          flags |= VIR_DUMP_MEMORY_ONLY;

-    if (virDomainCoreDump(dom, to, flags) < 0) {
+    optCompress = vshCommandOptBool(cmd, "compress");
+    if (optCompress && !(flags & VIR_DUMP_MEMORY_ONLY)) {
+        vshError(ctl, "%s",
+                 _("compress flag cannot be set without memory-only flag"));
+        goto out;
+    }
+
+    if (vshCommandOptString(cmd, "compression-format", &compression_format)) {
+        if (!optCompress) {
+            vshError(ctl, "%s",
+                     _("compression-format cannot be set without compress "
+                       "flag"));
+            goto out;
+        }
+
+        if (STREQ(compression_format, "zlib"))
+            memory_dump_format = VIR_MEMORY_DUMP_COMPRESS_ZLIB;
+        else if (STREQ(compression_format, "lzo"))
+            memory_dump_format = VIR_MEMORY_DUMP_COMPRESS_LZO;
+        else if (STREQ(compression_format, "snappy"))
+            memory_dump_format = VIR_MEMORY_DUMP_COMPRESS_SNAPPY;
+        else {
+            vshError(ctl, _("compression format '%s' is not supported, "
+                            "expecting 'zlib', 'lzo' or 'snappy'."),
+                     compression_format);
+            goto out;
+        }
+    } else {
+        if (optCompress)
+            memory_dump_format = VIR_MEMORY_DUMP_COMPRESS_ZLIB;
+    }
+
+    if (virDomainCoreDump(dom, to, flags, memory_dump_format) < 0) {
          vshError(ctl, _("Failed to core dump domain %s to %s"), name, to);
          goto out;
      }




More information about the libvir-list mailing list