
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