Through the watchdog actions, we can implement the docoredump func,
we rewrite the processWatchdogEvent function to serval independent functions,
so we move the previous implementation of the destroy and restart code to here.
then the code looks like easy.
---
src/qemu/qemu_driver.c | 197 +++++++++++++++++++++++++++++++++++++-----------
src/qemu/qemu_process.c | 118 +++++++++++++----------------
src/qemu/qemu_process.h | 2 +
3 files changed, 208 insertions(+), 109 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 4a76f14..4743539 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -3441,76 +3441,183 @@ cleanup:
return ret;
}
+static int
+qemuProcessWatchdogCrashEvent(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ int watchDogAction)
+{
+ int ret = -1;
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ virDomainEventPtr event = NULL;
+ bool isReset = false;
+
+ if (watchDogAction == VIR_DOMAIN_WATCHDOG_ACTION_CRASH_RESET ||
+ watchDogAction == VIR_DOMAIN_WATCHDOG_ACTION_CRASHDUMP_RESET)
+ isReset = true;
+
+ qemuDomainSetFakeReboot(driver, vm, isReset);
+
+ if (isReset) {
+ qemuProcessShutdownOrReboot(driver, vm);
+ return 0;
+ }
+
+ /* If isReset, then do follow. */
+ priv->beingDestroyed = true;
+
+ if (qemuProcessKill(vm, VIR_QEMU_PROCESS_KILL_FORCE) < 0) {
+ priv->beingDestroyed = false;
+ goto cleanup;
+ }
+
+ if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_DESTROY) < 0) {
+ goto cleanup;
+ }
+
+ priv->beingDestroyed = false;
+
+ if (! virDomainObjIsActive(vm)) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("domain is not running"));
+ goto endjob;
+ }
+
+ qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_CRASHED, 0);
+ event = virDomainEventNewFromObj(vm,
+ VIR_DOMAIN_EVENT_STOPPED,
+ VIR_DOMAIN_EVENT_STOPPED_CRASHED);
+
+ virDomainAuditStop(vm, "destroyed");
+
+ ret = 0;
+
+endjob:
+ /* Safe to ignore value since ref count was incremented in
+ * qemuProcessHandleWatchdog().
+ */
+ ignore_value(qemuDomainObjEndJob(driver, vm));
+
+cleanup:
+ if (event)
+ qemuDomainEventQueue(driver, event);
+ return ret;
+}
+
+
+static int
+qemuProcessWatchdogDumpEvent(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ int watchDogAction,
+ unsigned int flags)
+{
+ int ret = -1;
+ char *dumpfile = NULL;
+ virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+
+ if (virAsprintf(&dumpfile, "%s/%s-%u",
+ cfg->autoDumpPath,
+ vm->def->name,
+ (unsigned int)time(NULL)) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (qemuDomainObjBeginAsyncJob(driver, vm,
+ QEMU_ASYNC_JOB_DUMP) < 0) {
+ goto cleanup;
+ }
+
+ if (!virDomainObjIsActive(vm)) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("domain is not running"));
+ goto endjob;
+ }
+
+ flags |= cfg->autoDumpBypassCache ? VIR_DUMP_BYPASS_CACHE: 0;
+
+ ret = doCoreDump(driver, vm, dumpfile,
+ getCompressionType(driver), flags);
+ if (ret < 0)
+ virReportError(VIR_ERR_OPERATION_FAILED,
+ "%s", _("Dump failed"));
+
+ if (watchDogAction == VIR_DOMAIN_WATCHDOG_ACTION_DUMP) {
+ ret = qemuProcessStartCPUs(driver, vm, NULL,
+ VIR_DOMAIN_RUNNING_UNPAUSED,
+ QEMU_ASYNC_JOB_DUMP);
+
+ if (ret < 0)
+ virReportError(VIR_ERR_OPERATION_FAILED,
+ "%s", _("Resuming after dump failed"));
+ }
+
+endjob:
+ /* Safe to ignore value since ref count was incremented in
+ * qemuProcessHandleWatchdog().
+ */
+ ignore_value(qemuDomainObjEndAsyncJob(driver, vm));
+
+cleanup:
+ VIR_FREE(dumpfile);
+ virObjectUnref(cfg);
+ return ret;
+}
+
static void processWatchdogEvent(void *data, void *opaque)
{
int ret;
struct qemuDomainWatchdogEvent *wdEvent = data;
virQEMUDriverPtr driver = opaque;
- virQEMUDriverConfigPtr cfg;
virObjectLock(wdEvent->vm);
- cfg = virQEMUDriverGetConfig(driver);
switch (wdEvent->action) {
case VIR_DOMAIN_WATCHDOG_ACTION_DUMP:
{
- char *dumpfile;
unsigned int flags = 0;
+ qemuProcessWatchdogDumpEvent(driver, wdEvent->vm, wdEvent->action,
flags);
+ }
+ break;
+ case VIR_DOMAIN_WATCHDOG_ACTION_CRASHDUMP_DESTROY:
+ case VIR_DOMAIN_WATCHDOG_ACTION_CRASHDUMP_RESET:
+ {
+ unsigned int flags = VIR_DUMP_MEMORY_ONLY;
- if (virAsprintf(&dumpfile, "%s/%s-%u",
- cfg->autoDumpPath,
- wdEvent->vm->def->name,
- (unsigned int)time(NULL)) < 0) {
- virReportOOMError();
- goto unlock;
- }
-
- if (qemuDomainObjBeginAsyncJob(driver, wdEvent->vm,
- QEMU_ASYNC_JOB_DUMP) < 0) {
- VIR_FREE(dumpfile);
- goto unlock;
- }
+ ret = qemuProcessWatchdogDumpEvent(driver, wdEvent->vm,
wdEvent->action, flags);
- if (!virDomainObjIsActive(wdEvent->vm)) {
- virReportError(VIR_ERR_OPERATION_INVALID,
- "%s", _("domain is not running"));
- VIR_FREE(dumpfile);
- goto endjob;
- }
-
- flags |= cfg->autoDumpBypassCache ? VIR_DUMP_BYPASS_CACHE: 0;
- ret = doCoreDump(driver, wdEvent->vm, dumpfile,
- getCompressionType(driver), flags);
if (ret < 0)
- virReportError(VIR_ERR_OPERATION_FAILED,
- "%s", _("Dump failed"));
+ goto unlock;
- ret = qemuProcessStartCPUs(driver, wdEvent->vm, NULL,
- VIR_DOMAIN_RUNNING_UNPAUSED,
- QEMU_ASYNC_JOB_DUMP);
+ qemuProcessWatchdogCrashEvent(driver, wdEvent->vm, wdEvent->action);
- if (ret < 0)
- virReportError(VIR_ERR_OPERATION_FAILED,
- "%s", _("Resuming after dump
failed"));
-
- VIR_FREE(dumpfile);
+ if (wdEvent->action == VIR_DOMAIN_WATCHDOG_ACTION_CRASHDUMP_DESTROY) {
+ if (!wdEvent->vm->persistent) {
+ qemuDomainRemoveInactive(driver, wdEvent->vm);
+ wdEvent->vm = NULL;
+ }
+ }
+ }
+ break;
+ case VIR_DOMAIN_WATCHDOG_ACTION_CRASH_RESET:
+ case VIR_DOMAIN_WATCHDOG_ACTION_CRASH_DESTROY:
+ qemuProcessWatchdogCrashEvent(driver, wdEvent->vm, wdEvent->action);
+ if (wdEvent->action == VIR_DOMAIN_WATCHDOG_ACTION_CRASH_DESTROY) {
+ if (!wdEvent->vm->persistent) {
+ qemuDomainRemoveInactive(driver, wdEvent->vm);
+ wdEvent->vm = NULL;
+ }
}
break;
default:
goto unlock;
}
-endjob:
- /* Safe to ignore value since ref count was incremented in
- * qemuProcessHandleWatchdog().
- */
- ignore_value(qemuDomainObjEndAsyncJob(driver, wdEvent->vm));
-
unlock:
- virObjectUnlock(wdEvent->vm);
- virObjectUnref(wdEvent->vm);
+ if (wdEvent->vm) {
+ virObjectUnlock(wdEvent->vm);
+ virObjectUnref(wdEvent->vm);
+ }
VIR_FREE(wdEvent);
- virObjectUnref(cfg);
}
static int qemuDomainHotplugVcpus(virQEMUDriverPtr driver,
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 29c8c4b..9100a67 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -615,7 +615,7 @@ cleanup:
}
-static void
+void
qemuProcessShutdownOrReboot(virQEMUDriverPtr driver,
virDomainObjPtr vm)
{
@@ -816,6 +816,27 @@ qemuProcessHandleRTCChange(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
return 0;
}
+static void sendWatchDogEvent(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ int action)
+{
+ struct qemuDomainWatchdogEvent *wdEvent = NULL;
+ if (VIR_ALLOC(wdEvent) == 0) {
+ wdEvent->action = action;
+ wdEvent->vm = vm;
+ /* Hold an extra reference because we can't allow 'vm' to be
+ * deleted before handling watchdog event is finished.
+ */
+ virObjectRef(vm);
+ if (virThreadPoolSendJob(driver->workerPool, 0, wdEvent) < 0) {
+ if (!virObjectUnref(vm))
+ vm = NULL;
+ VIR_FREE(wdEvent);
+ }
+ } else {
+ virReportOOMError();
+ }
+}
static int
qemuProcessHandleWatchdog(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
@@ -852,22 +873,7 @@ qemuProcessHandleWatchdog(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
}
if (vm->def->watchdog->action == VIR_DOMAIN_WATCHDOG_ACTION_DUMP) {
- struct qemuDomainWatchdogEvent *wdEvent;
- if (VIR_ALLOC(wdEvent) == 0) {
- wdEvent->action = VIR_DOMAIN_WATCHDOG_ACTION_DUMP;
- wdEvent->vm = vm;
- /* Hold an extra reference because we can't allow 'vm' to be
- * deleted before handling watchdog event is finished.
- */
- virObjectRef(vm);
- if (virThreadPoolSendJob(driver->workerPool, 0, wdEvent) < 0) {
- if (!virObjectUnref(vm))
- vm = NULL;
- VIR_FREE(wdEvent);
- }
- } else {
- virReportOOMError();
- }
+ sendWatchDogEvent(driver, vm, VIR_DOMAIN_WATCHDOG_ACTION_DUMP);
}
if (vm)
@@ -1273,6 +1279,7 @@ qemuProcessHandlePMSuspendDisk(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
return 0;
}
+
static int
qemuProcessHandleGUESTPanicked(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
virDomainObjPtr vm)
@@ -1280,8 +1287,8 @@ qemuProcessHandleGUESTPanicked(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
virQEMUDriverPtr driver = qemu_driver;
qemuDomainObjPrivatePtr priv;
virDomainEventPtr event = NULL;
- bool isReboot = true;
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+ int watchDogAction = VIR_DOMAIN_WATCHDOG_ACTION_NONE;
VIR_DEBUG("vm=%p", vm);
@@ -1295,6 +1302,9 @@ qemuProcessHandleGUESTPanicked(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
priv = vm->privateData;
+ VIR_DEBUG("Transitioned guest %s to crashed state for panic",
+ vm->def->name);
+
virDomainObjSetState(vm,
VIR_DOMAIN_CRASHED,
VIR_DOMAIN_CRASHED_PANICKED);
@@ -1303,58 +1313,38 @@ qemuProcessHandleGUESTPanicked(qemuMonitorPtr mon
ATTRIBUTE_UNUSED,
VIR_DOMAIN_EVENT_CRASHED,
VIR_DOMAIN_EVENT_CRASHED_PANICKED);
- if (vm->def->onCrash == VIR_DOMAIN_LIFECYCLE_CRASH_PRESERVE) {
- VIR_FREE(priv->lockState);
-
- if (virDomainLockProcessPause(driver->lockManager, vm,
&priv->lockState) < 0)
- VIR_WARN("Unable to release lease on %s", vm->def->name);
- VIR_DEBUG("Preserving lock state '%s'",
NULLSTR(priv->lockState));
+ VIR_FREE(priv->lockState);
- if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) {
- VIR_WARN("Unable to save status on vm %s after state change",
- vm->def->name);
- }
+ if (virDomainLockProcessPause(driver->lockManager, vm, &priv->lockState)
< 0)
+ VIR_WARN("Unable to release lease on %s", vm->def->name);
+ VIR_DEBUG("Preserving lock state '%s'",
NULLSTR(priv->lockState));
- goto cleanup;
+ if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) {
+ VIR_WARN("Unable to save status on vm %s after state change",
+ vm->def->name);
}
- if (vm->def->onCrash == VIR_DOMAIN_LIFECYCLE_CRASH_DESTROY) {
- isReboot = false;
- VIR_INFO("Domain on_crash setting overridden, shutting down");
+ switch (vm->def->onCrash) {
+ case VIR_DOMAIN_LIFECYCLE_CRASH_PRESERVE:
+ break;
+ case VIR_DOMAIN_LIFECYCLE_CRASH_DESTROY:
+ watchDogAction = VIR_DOMAIN_WATCHDOG_ACTION_CRASH_DESTROY;
+ break;
+ case VIR_DOMAIN_LIFECYCLE_CRASH_COREDUMP_DESTROY:
+ watchDogAction = VIR_DOMAIN_WATCHDOG_ACTION_CRASHDUMP_DESTROY;
+ break;
+ case VIR_DOMAIN_LIFECYCLE_CRASH_RESTART_RENAME:
+ /* unrealized */
+ break;
+ case VIR_DOMAIN_LIFECYCLE_CRASH_RESTART:
+ watchDogAction = VIR_DOMAIN_WATCHDOG_ACTION_CRASH_RESET;
+ break;
+ case VIR_DOMAIN_LIFECYCLE_CRASH_COREDUMP_RESTART:
+ watchDogAction = VIR_DOMAIN_WATCHDOG_ACTION_CRASHDUMP_RESET;
+ break;
}
- qemuDomainSetFakeReboot(driver, vm, isReboot);
-
- if (isReboot) {
- qemuProcessShutdownOrReboot(driver, vm);
- } else {
- priv->beingDestroyed = true;
-
- if (qemuProcessKill(vm, VIR_QEMU_PROCESS_KILL_FORCE) < 0) {
- priv->beingDestroyed = false;
- goto cleanup;
- }
-
- priv->beingDestroyed = false;
-
- if (! virDomainObjIsActive(vm)) {
- virReportError(VIR_ERR_OPERATION_INVALID,
- "%s", _("domain is not running"));
- goto cleanup;
- }
-
- qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_CRASHED, 0);
- event = virDomainEventNewFromObj(vm,
- VIR_DOMAIN_EVENT_STOPPED,
- VIR_DOMAIN_EVENT_STOPPED_CRASHED);
-
- virDomainAuditStop(vm, "destroyed");
-
- if (! vm->persistent) {
- qemuDomainRemoveInactive(driver, vm);
- vm = NULL;
- }
- }
+ sendWatchDogEvent(driver, vm, watchDogAction);
cleanup:
if (vm)
diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h
index d4768fc..9223e07 100644
--- a/src/qemu/qemu_process.h
+++ b/src/qemu/qemu_process.h
@@ -86,6 +86,8 @@ typedef enum {
int qemuProcessKill(virDomainObjPtr vm, unsigned int flags);
+void qemuProcessShutdownOrReboot(virQEMUDriverPtr driver,
+ virDomainObjPtr vm);
int qemuProcessAutoDestroyInit(virQEMUDriverPtr driver);
void qemuProcessAutoDestroyShutdown(virQEMUDriverPtr driver);
int qemuProcessAutoDestroyAdd(virQEMUDriverPtr driver,
--
1.8.1.4