[libvirt] [PATCH 2/3 v5] qemu: allow the client to choose the vmcore's format

Martin Kletzander mkletzan at redhat.com
Wed Jun 13 12:57:03 UTC 2012


On 06/12/2012 05:06 AM, Wen Congyang wrote:
> This patch updates qemu driver to allow the client to choose the
> vmcore's format: memory only or including device state.
> ---
>  include/libvirt/libvirt.h.in |    1 +
>  src/qemu/qemu_capabilities.c |    5 +++
>  src/qemu/qemu_capabilities.h |    1 +
>  src/qemu/qemu_domain.c       |    1 +
>  src/qemu/qemu_domain.h       |    1 +
>  src/qemu/qemu_driver.c       |   60 ++++++++++++++++++++++++++++++++---------
>  6 files changed, 56 insertions(+), 13 deletions(-)
> 
> diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
> index fcb6695..120ed14 100644
> --- a/include/libvirt/libvirt.h.in
> +++ b/include/libvirt/libvirt.h.in
> @@ -927,6 +927,7 @@ typedef enum {
>      VIR_DUMP_LIVE         = (1 << 1), /* live dump */
>      VIR_DUMP_BYPASS_CACHE = (1 << 2), /* avoid file system cache pollution */
>      VIR_DUMP_RESET        = (1 << 3), /* reset domain after dump finishes */
> +    VIR_DUMP_MEMORY_ONLY  = (1 << 4), /* use dump-guest-memory */
>  } virDomainCoreDumpFlags;
>  
>  /* Domain migration flags. */
> diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
> index b410648..6eee8cd 100644
> --- a/src/qemu/qemu_capabilities.c
> +++ b/src/qemu/qemu_capabilities.c
> @@ -164,6 +164,7 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST,
>                "no-user-config",
>  
>                "hda-micro", /* 95 */
> +              "dump-guest-memory",
>  
>      );
>  
> @@ -1237,6 +1238,10 @@ qemuCapsComputeCmdFlags(const char *help,
>  
>      if (version >= 11000)
>          qemuCapsSet(flags, QEMU_CAPS_CPU_HOST);
> +
> +    if (version >= 1001050)
> +        qemuCapsSet(flags, QEMU_CAPS_DUMP_GUEST_MEMORY);
> +
>      return 0;
>  }
>  

Sorry for bothering you with this, but I tried newest qemu and it shows
the proper list of commands with query-commands in qmp. Instead of this
one hunk, I'd use this:

diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 6ca01c5..7d2da21 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -991,6 +991,8 @@ qemuMonitorJSONCheckCommands(qemuMonitorPtr mon,
             qemuCapsSet(qemuCaps, QEMU_CAPS_BLOCKJOB_SYNC);
         else if (STREQ(name, "block-job-cancel"))
             qemuCapsSet(qemuCaps, QEMU_CAPS_BLOCKJOB_ASYNC);
+        else if (STREQ(name, "dump-guest-memory"))
+            qemuCapsSet(qemuCaps, QEMU_CAPS_DUMP_GUEST_MEMORY);
     }

     ret = 0;

> diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
> index 64831e2..640f7f5 100644
> --- a/src/qemu/qemu_capabilities.h
> +++ b/src/qemu/qemu_capabilities.h
> @@ -131,6 +131,7 @@ enum qemuCapsFlags {
>      QEMU_CAPS_IDE_CD             = 93, /* -device ide-cd */
>      QEMU_CAPS_NO_USER_CONFIG     = 94, /* -no-user-config */
>      QEMU_CAPS_HDA_MICRO          = 95, /* -device hda-micro */
> +    QEMU_CAPS_DUMP_GUEST_MEMORY  = 96, /* dump-guest-memory command */
>  
>      QEMU_CAPS_LAST,                   /* this must always be the last item */
>  };
> diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
> index 3752ddf..91c0645 100644
> --- a/src/qemu/qemu_domain.c
> +++ b/src/qemu/qemu_domain.c
> @@ -160,6 +160,7 @@ qemuDomainObjResetAsyncJob(qemuDomainObjPrivatePtr priv)
>      job->phase = 0;
>      job->mask = DEFAULT_JOB_MASK;
>      job->start = 0;
> +    job->dump_memory_only = false;
>      memset(&job->info, 0, sizeof(job->info));
>  }
>  
> diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
> index 1256c4e..3a5f1f3 100644
> --- a/src/qemu/qemu_domain.h
> +++ b/src/qemu/qemu_domain.h
> @@ -104,6 +104,7 @@ struct qemuDomainJobObj {
>      int phase;                          /* Job phase (mainly for migrations) */
>      unsigned long long mask;            /* Jobs allowed during async job */
>      unsigned long long start;           /* When the async job started */
> +    bool dump_memory_only;              /* use dump-guest-memory to do dump */
>      virDomainJobInfo info;              /* Async job progress data */
>  };
>  
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index d3f74d2..b2da838 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -2986,12 +2986,39 @@ cleanup:
>      return ret;
>  }
>  
> +static int qemuDumpToFd(struct qemud_driver *driver, virDomainObjPtr vm,
> +                        int fd, enum qemuDomainAsyncJob asyncJob)
> +{
> +    qemuDomainObjPrivatePtr priv = vm->privateData;
> +    int ret = -1;
> +
> +    if (!qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DUMP_GUEST_MEMORY)) {
> +        qemuReportError(VIR_ERR_NO_SUPPORT, "%s",
> +                        _("dump-guest-memory is not supported"));
> +        return -1;
> +    }
> +
> +    if (virSecurityManagerSetImageFDLabel(driver->securityManager, vm->def,
> +                                          fd) < 0)
> +        return -1;
> +
> +    priv->job.dump_memory_only = true;
> +
> +    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
> +        return -1;
> +
> +    ret = qemuMonitorDumpToFd(priv->mon, 0, fd, 0, 0);
> +    qemuDomainObjExitMonitorWithDriver(driver, vm);
> +
> +    return ret;
> +}
> +
>  static int
>  doCoreDump(struct qemud_driver *driver,
>             virDomainObjPtr vm,
>             const char *path,
>             enum qemud_save_formats compress,
> -           bool bypass_cache)
> +           unsigned int dump_flags)
>  {
>      int fd = -1;
>      int ret = -1;
> @@ -3000,7 +3027,7 @@ doCoreDump(struct qemud_driver *driver,
>      unsigned int flags = VIR_FILE_WRAPPER_NON_BLOCKING;
>  
>      /* Create an empty file with appropriate ownership.  */
> -    if (bypass_cache) {
> +    if (dump_flags & VIR_DUMP_BYPASS_CACHE) {
>          flags |= VIR_FILE_WRAPPER_BYPASS_CACHE;
>          directFlag = virFileDirectFdFlag();
>          if (directFlag < 0) {
> @@ -3020,14 +3047,20 @@ doCoreDump(struct qemud_driver *driver,
>      if (!(wrapperFd = virFileWrapperFdNew(&fd, path, flags)))
>          goto cleanup;
>  
> -    if (qemuMigrationToFile(driver, vm, fd, 0, path,
> -                            qemuCompressProgramName(compress), false,
> -                            QEMU_ASYNC_JOB_DUMP) < 0)
> +    if (dump_flags & VIR_DUMP_MEMORY_ONLY) {
> +        ret = qemuDumpToFd(driver, vm, fd, QEMU_ASYNC_JOB_DUMP);
> +    } else {
> +        ret = qemuMigrationToFile(driver, vm, fd, 0, path,
> +                                  qemuCompressProgramName(compress), false,
> +                                  QEMU_ASYNC_JOB_DUMP);
> +    }
> +
> +    if (ret < 0)
>          goto cleanup;
>  
>      if (VIR_CLOSE(fd) < 0) {
>          virReportSystemError(errno,
> -                             _("unable to save file %s"),
> +                             _("unable to close file %s"),
>                               path);
>          goto cleanup;
>      }
> @@ -3085,7 +3118,8 @@ static int qemudDomainCoreDump(virDomainPtr dom,
>      virDomainEventPtr event = NULL;
>  
>      virCheckFlags(VIR_DUMP_LIVE | VIR_DUMP_CRASH |
> -                  VIR_DUMP_BYPASS_CACHE | VIR_DUMP_RESET, -1);
> +                  VIR_DUMP_BYPASS_CACHE | VIR_DUMP_RESET |
> +                  VIR_DUMP_MEMORY_ONLY, -1);
>  
>      qemuDriverLock(driver);
>      vm = virDomainFindByUUID(&driver->domains, dom->uuid);
> @@ -3127,8 +3161,7 @@ static int qemudDomainCoreDump(virDomainPtr dom,
>          }
>      }
>  
> -    ret = doCoreDump(driver, vm, path, getCompressionType(driver),
> -                     (flags & VIR_DUMP_BYPASS_CACHE) != 0);
> +    ret = doCoreDump(driver, vm, path, getCompressionType(driver), flags);
>      if (ret < 0)
>          goto endjob;
>  
> @@ -3289,6 +3322,7 @@ static void processWatchdogEvent(void *data, void *opaque)
>      case VIR_DOMAIN_WATCHDOG_ACTION_DUMP:
>          {
>              char *dumpfile;
> +            unsigned int flags = 0;
>  
>              if (virAsprintf(&dumpfile, "%s/%s-%u",
>                              driver->autoDumpPath,
> @@ -3311,9 +3345,9 @@ static void processWatchdogEvent(void *data, void *opaque)
>                  goto endjob;
>              }
>  
> +            flags |= driver->autoDumpBypassCache ? VIR_DUMP_BYPASS_CACHE: 0;
>              ret = doCoreDump(driver, wdEvent->vm, dumpfile,
> -                             getCompressionType(driver),
> -                             driver->autoDumpBypassCache);
> +                             getCompressionType(driver), flags);
>              if (ret < 0)
>                  qemuReportError(VIR_ERR_OPERATION_FAILED,
>                                  "%s", _("Dump failed"));
> @@ -9402,7 +9436,7 @@ static int qemuDomainGetJobInfo(virDomainPtr dom,
>      priv = vm->privateData;
>  
>      if (virDomainObjIsActive(vm)) {
> -        if (priv->job.asyncJob) {
> +        if (priv->job.asyncJob && !priv->job.dump_memory_only) {
>              memcpy(info, &priv->job.info, sizeof(*info));
>  
>              /* Refresh elapsed time again just to ensure it
> @@ -9460,7 +9494,7 @@ static int qemuDomainAbortJob(virDomainPtr dom) {
>  
>      priv = vm->privateData;
>  
> -    if (!priv->job.asyncJob) {
> +    if (!priv->job.asyncJob || priv->job.dump_memory_only) {
>          qemuReportError(VIR_ERR_OPERATION_INVALID,
>                          "%s", _("no job is active on the domain"));
>          goto endjob;
> 

, so ACK with that one hunk changed.

Martin




More information about the libvir-list mailing list