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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list