}
}
+ p = virConfGetValue (conf, "auto_dump_path");
+ CHECK_TYPE ("auto_dump_path", VIR_CONF_STRING);
+ if (p && p->str) {
+ VIR_FREE(driver->autoDumpPath);
+ if (!(driver->autoDumpPath = strdup(p->str))) {
+ virReportOOMError();
+ virConfFree(conf);
+ return -1;
+ }
+ }
+
p = virConfGetValue (conf, "hugetlbfs_mount");
CHECK_TYPE ("hugetlbfs_mount", VIR_CONF_STRING);
if (p && p->str) {
virCommandAddArg(cmd, optstr);
VIR_FREE(optstr);
- const char *action = virDomainWatchdogActionTypeToString(watchdog->action);
+ int act = watchdog->action;
+ if (act == VIR_DOMAIN_WATCHDOG_ACTION_DUMP)
+ act = VIR_DOMAIN_WATCHDOG_ACTION_PAUSE;
+ const char *action = virDomainWatchdogActionTypeToString(act);
if (!action) {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("invalid watchdog action"));
#include "files.h"
#include "fdstream.h"
#include "configmake.h"
+#include "threadpool.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
int persistentAddrs;
};
+struct watchdogEvent
+{
+ virDomainObjPtr vm;
+ int action;
+};
+
+static void processWatchdogEvent(void *data, void *opaque);
+
static int qemudShutdown(void);
static void qemuDriverLock(struct qemud_driver *driver)
if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
VIR_WARN("Unable to save status on vm %s after IO error", vm->def->name);
}
+
+ if (vm->def->watchdog->action == VIR_DOMAIN_WATCHDOG_ACTION_DUMP) {
+ struct watchdogEvent *wdEvent;
+ if (VIR_ALLOC(wdEvent) == 0) {
+ wdEvent->action = VIR_DOMAIN_WATCHDOG_ACTION_DUMP;
+ wdEvent->vm = vm;
+ ignore_value(virThreadPoolSendJob(driver->workerPool, wdEvent));
+ } else
+ virReportOOMError();
+ }
+
virDomainObjUnlock(vm);
if (watchdogEvent || lifecycleEvent) {
if (virAsprintf(&qemu_driver->snapshotDir,
"%s/lib/libvirt/qemu/snapshot", LOCALSTATEDIR) == -1)
goto out_of_memory;
+ if (virAsprintf(&qemu_driver->autoDumpPath,
+ "%s/lib/libvirt/qemu/dump", LOCALSTATEDIR) == -1)
+ goto out_of_memory;
} else {
uid_t uid = geteuid();
char *userdir = virGetUserDirectory(uid);
goto out_of_memory;
if (virAsprintf(&qemu_driver->snapshotDir, "%s/qemu/snapshot", base) == -1)
goto out_of_memory;
+ if (virAsprintf(&qemu_driver->autoDumpPath, "%s/qemu/dump", base) == -1)
+ goto out_of_memory;
}
if (virFileMakePath(qemu_driver->stateDir) != 0) {
qemu_driver->snapshotDir, virStrerror(errno, ebuf, sizeof ebuf));
goto error;
}
+ if (virFileMakePath(qemu_driver->autoDumpPath) != 0) {
+ char ebuf[1024];
+ VIR_ERROR(_("Failed to create dump dir '%s': %s"),
+ qemu_driver->autoDumpPath, virStrerror(errno, ebuf, sizeof ebuf));
+ goto error;
+ }
/* Configuration paths are either ~/.libvirt/qemu/... (session) or
* /etc/libvirt/qemu/... (system).
qemudAutostartConfigs(qemu_driver);
+ qemu_driver->workerPool = virThreadPoolNew(0, 1, processWatchdogEvent, qemu_driver);
+ if (!qemu_driver->workerPool)
+ goto error;
+
if (conn)
virConnectClose(conn);
VIR_FREE(qemu_driver->cacheDir);
VIR_FREE(qemu_driver->saveDir);
VIR_FREE(qemu_driver->snapshotDir);
+ VIR_FREE(qemu_driver->autoDumpPath);
VIR_FREE(qemu_driver->vncTLSx509certdir);
VIR_FREE(qemu_driver->vncListen);
VIR_FREE(qemu_driver->vncPassword);
qemuDriverUnlock(qemu_driver);
virMutexDestroy(&qemu_driver->lock);
+ virThreadPoolFree(qemu_driver->workerPool);
VIR_FREE(qemu_driver);
return 0;
return ret;
}
+static void processWatchdogEvent(void *data, void *opaque)
+{
+ int ret;
+ struct watchdogEvent *wdEvent = data;
+ struct qemud_driver *driver = opaque;
+
+ switch (wdEvent->action) {
+ case VIR_DOMAIN_WATCHDOG_ACTION_DUMP:
+ {
+ char *dumpfile;
+ int i;
+
+ qemuDomainObjPrivatePtr priv = wdEvent->vm->privateData;
+
+ i = virAsprintf(&dumpfile, "%s/%s-%u",
+ driver->autoDumpPath,
+ wdEvent->vm->def->name,
+ (unsigned int)time(NULL));
+
+ qemuDriverLock(driver);
+ virDomainObjLock(wdEvent->vm);
+
+ if (qemuDomainObjBeginJobWithDriver(driver, wdEvent->vm) < 0)
+ break;
+
+ if (!virDomainObjIsActive(wdEvent->vm)) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("domain is not running"));
+ break;
+ }
+
+ ret = doCoreDump(driver,
+ wdEvent->vm,
+ dumpfile,
+ getCompressionType(driver));
+ if (ret < 0)
+ qemuReportError(VIR_ERR_OPERATION_FAILED,
+ "%s", _("Dump failed"));
+
+ qemuDomainObjEnterMonitorWithDriver(driver, wdEvent->vm);
+ ret = qemuMonitorStartCPUs(priv->mon, NULL);
+ qemuDomainObjExitMonitorWithDriver(driver, wdEvent->vm);
+
+ if (ret < 0)
+ qemuReportError(VIR_ERR_OPERATION_FAILED,
+ "%s", _("Resuming after dump failed"));
+
+ if (qemuDomainObjEndJob(wdEvent->vm) > 0)
+ virDomainObjUnlock(wdEvent->vm);
+
+ qemuDriverUnlock(driver);
+
+ VIR_FREE(dumpfile);
+ }
+ break;
+ }
+
+ VIR_FREE(wdEvent);
+}
static int qemudDomainHotplugVcpus(virDomainObjPtr vm, unsigned int nvcpus)
{