qemu: allow the client to choose the vmcore's format

This patch updates qemu driver to allow the client to choose the
vmcore's format: memory only or including device state.
This commit is contained in:
Wen Congyang 2012-06-12 11:06:33 +08:00
parent 6fe26d89cc
commit cdef31c562
7 changed files with 54 additions and 13 deletions

View File

@ -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. */

View File

@ -164,6 +164,7 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST,
"no-user-config",
"hda-micro", /* 95 */
"dump-guest-memory",
);

View File

@ -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 */
};

View File

@ -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));
}

View File

@ -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 */
};

View File

@ -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;

View File

@ -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;