This patch makes use of the virDomainObjPtr locking infrastructure to
provide thread safety in the QEMU driver. The QEMU driver itself gains
a global lock. The idea is this lock is only held for short periods of
time - typically only while obtaining a virDomainObjPtr instance.
The main limitation of the current locking implemented here, is that
the virDomainObjPtr lock is held for the duration of all monitor
commands. Some of these can take quite a long time to execute, so for
a useful level of concurrency we need to drop the lock & reobtain it
when issuing monitor commands. I intend to deal with this problem in
an add-on patch, since I'd rather keep the initial impl simple to
understand.
The general model for an API call involving a virDomainPtr is
qemudXXXXX(virDomainPtr dom) {
struct qemud_driver *driver = conn->privateData;
virDomainObjPtr vm;
qemudDriverLock(driver);
vm = virDomainFindByUUID(&driver->domains, uuid);
qemudDriverUnlock(driver);
.... do work ....
virDomainObjUnlock(vm);
return 0;
error:
virDomainObjUnlock(vm);
return -1;
}
The important thing to note is that if anything goes wrong in the
'... do work...' bit of the driver call, it should never do
a direct 'return -1;'. It must always 'goto error' instead. This
avoids the need to sprinkle calls to virDomainObjUnlock(vm)
everywhere.
Daniel
diff --git a/src/qemu_conf.h b/src/qemu_conf.h
--- a/src/qemu_conf.h
+++ b/src/qemu_conf.h
@@ -48,6 +48,8 @@ enum qemud_cmd_flags {
/* Main driver state */
struct qemud_driver {
+ pthread_mutex_t lock;
+
unsigned int qemuVersion;
int nextvmid;
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -76,6 +76,22 @@ static int qemudShutdown(void);
#define qemudLog(level, msg...) fprintf(stderr, msg)
+
+static int
+qemudDriverLock(struct qemud_driver *driver)
+{
+ DEBUG("LOCK driver %p %p", (driver), (void*)pthread_self());
+ return pthread_mutex_lock(&(driver)->lock);
+}
+
+static int
+qemudDriverUnlock(struct qemud_driver *driver)
+{
+ DEBUG("UNLOCK driver %p %p", (driver), (void*)pthread_self());
+ return pthread_mutex_unlock(&(driver)->lock);
+}
+
+
static int qemudSetCloseExec(int fd) {
int flags;
if ((flags = fcntl(fd, F_GETFD)) < 0)
@@ -130,13 +146,18 @@ qemudAutostartConfigs(struct qemud_drive
unsigned int i;
for (i = 0 ; i < driver->domains.count ; i++) {
- if (driver->domains.objs[i]->autostart &&
- !virDomainIsActive(driver->domains.objs[i]) &&
- qemudStartVMDaemon(NULL, driver, driver->domains.objs[i], NULL) < 0) {
+ virDomainObjPtr dom = driver->domains.objs[i];
+ virDomainLock(dom);
+
+ if (dom->autostart &&
+ !virDomainIsActive(dom) &&
+ qemudStartVMDaemon(NULL, driver, dom, NULL) < 0) {
virErrorPtr err = virGetLastError();
qemudLog(QEMUD_ERR, _("Failed to autostart VM '%s':
%s\n"),
- driver->domains.objs[i]->def->name, err->message);
+ dom->def->name, err->message);
}
+
+ virDomainUnlock(dom);
}
}
@@ -157,6 +178,7 @@ qemudStartup(void) {
/* Don't have a dom0 so start from 1 */
qemu_driver->nextvmid = 1;
+ pthread_mutex_init(&qemu_driver->lock, NULL);
if (!uid) {
if (asprintf(&qemu_driver->logDir,
@@ -203,15 +225,20 @@ qemudStartup(void) {
return -1;
}
+ qemudDriverLock(qemu_driver);
+
if (virDomainLoadAllConfigs(NULL,
qemu_driver->caps,
&qemu_driver->domains,
qemu_driver->configDir,
qemu_driver->autostartDir) < 0) {
+ qemudDriverUnlock(qemu_driver);
qemudShutdown();
return -1;
}
qemudAutostartConfigs(qemu_driver);
+
+ qemudDriverUnlock(qemu_driver);
return 0;
@@ -235,6 +262,8 @@ qemudReload(void) {
if (!qemu_driver)
return 0;
+ qemudDriverLock(qemu_driver);
+
virDomainLoadAllConfigs(NULL,
qemu_driver->caps,
&qemu_driver->domains,
@@ -242,6 +271,8 @@ qemudReload(void) {
qemu_driver->autostartDir);
qemudAutostartConfigs(qemu_driver);
+
+ qemudDriverUnlock(qemu_driver);
return 0;
}
@@ -257,16 +288,23 @@ static int
static int
qemudActive(void) {
unsigned int i;
+ int isactive = 0;
if (!qemu_driver)
return 0;
- for (i = 0 ; i < qemu_driver->domains.count ; i++)
+ qemudDriverLock(qemu_driver);
+
+ for (i = 0 ; i < qemu_driver->domains.count ; i++) {
+ virDomainLock(qemu_driver->domains.objs[i]);
if (virDomainIsActive(qemu_driver->domains.objs[i]))
- return 1;
+ isactive = 1;
+ virDomainUnlock(qemu_driver->domains.objs[i]);
+ }
- /* Otherwise we're happy to deal with a shutdown */
- return 0;
+ qemudDriverUnlock(qemu_driver);
+
+ return isactive;
}
/**
@@ -1222,12 +1260,16 @@ static char *qemudGetCapabilities(virCon
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
char *xml;
+ qemudDriverLock(driver);
+
if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL) {
+ qemudDriverUnlock(driver);
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
"%s", _("failed to allocate space for capabilities
support"));
return NULL;
}
+ qemudDriverUnlock(driver);
return xml;
}
@@ -1327,8 +1369,12 @@ static virDomainPtr qemudDomainLookupByI
static virDomainPtr qemudDomainLookupByID(virConnectPtr conn,
int id) {
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
- virDomainObjPtr vm = virDomainFindByID(&driver->domains, id);
+ virDomainObjPtr vm;
virDomainPtr dom;
+
+ qemudDriverLock(driver);
+ vm = virDomainFindByID(&driver->domains, id);
+ qemudDriverUnlock(driver);
if (!vm) {
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
@@ -1337,13 +1383,19 @@ static virDomainPtr qemudDomainLookupByI
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
if (dom) dom->id = vm->def->id;
+
+ virDomainUnlock(vm);
return dom;
}
static virDomainPtr qemudDomainLookupByUUID(virConnectPtr conn,
const unsigned char *uuid) {
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
- virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, uuid);
+ virDomainObjPtr vm;
virDomainPtr dom;
+
+ qemudDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, uuid);
+ qemudDriverUnlock(driver);
if (!vm) {
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
@@ -1352,13 +1404,19 @@ static virDomainPtr qemudDomainLookupByU
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
if (dom) dom->id = vm->def->id;
+
+ virDomainUnlock(vm);
return dom;
}
static virDomainPtr qemudDomainLookupByName(virConnectPtr conn,
const char *name) {
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
- virDomainObjPtr vm = virDomainFindByName(&driver->domains, name);
+ virDomainObjPtr vm;
virDomainPtr dom;
+
+ qemudDriverLock(driver);
+ vm = virDomainFindByName(&driver->domains, name);
+ qemudDriverUnlock(driver);
if (!vm) {
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
@@ -1367,15 +1425,23 @@ static virDomainPtr qemudDomainLookupByN
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
if (dom) dom->id = vm->def->id;
+
+ virDomainUnlock(vm);
return dom;
}
static int qemudGetVersion(virConnectPtr conn, unsigned long *version) {
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
- if (qemudExtractVersion(conn, driver) < 0)
+ qemudDriverLock(driver);
+
+ if (qemudExtractVersion(conn, driver) < 0) {
+ qemudDriverUnlock(driver);
return -1;
+ }
*version = qemu_driver->qemuVersion;
+
+ qemudDriverUnlock(driver);
return 0;
}
@@ -1405,39 +1471,51 @@ static int qemudListDomains(virConnectPt
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
int got = 0, i;
- for (i = 0 ; i < driver->domains.count && got < nids ; i++)
+ qemudDriverLock(driver);
+ for (i = 0 ; i < driver->domains.count && got < nids ; i++) {
+ virDomainLock(driver->domains.objs[i]);
if (virDomainIsActive(driver->domains.objs[i]))
ids[got++] = driver->domains.objs[i]->def->id;
+ virDomainUnlock(driver->domains.objs[i]);
+ }
+ qemudDriverUnlock(driver);
return got;
}
+
static int qemudNumDomains(virConnectPtr conn) {
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
int n = 0, i;
- for (i = 0 ; i < driver->domains.count ; i++)
+ qemudDriverLock(driver);
+ for (i = 0 ; i < driver->domains.count ; i++) {
+ virDomainLock(driver->domains.objs[i]);
if (virDomainIsActive(driver->domains.objs[i]))
n++;
+ virDomainUnlock(driver->domains.objs[i]);
+ }
+ qemudDriverUnlock(driver);
return n;
}
static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
unsigned int flags ATTRIBUTE_UNUSED) {
virDomainDefPtr def;
- virDomainObjPtr vm;
+ virDomainObjPtr vm = NULL;
virDomainPtr dom;
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
+ qemudDriverLock(driver);
+
if (!(def = virDomainDefParseString(conn, driver->caps, xml)))
- return NULL;
+ goto cleanup;
vm = virDomainFindByName(&driver->domains, def->name);
if (vm) {
qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
_("domain '%s' is already defined"),
def->name);
- virDomainDefFree(def);
- return NULL;
+ goto cleanup;
}
vm = virDomainFindByUUID(&driver->domains, def->uuid);
if (vm) {
@@ -1447,149 +1525,225 @@ static virDomainPtr qemudDomainCreate(vi
qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
_("domain with uuid '%s' is already
defined"),
uuidstr);
- virDomainDefFree(def);
- return NULL;
+ goto cleanup;
}
if (!(vm = virDomainAssignDef(conn,
&driver->domains,
- def))) {
- virDomainDefFree(def);
- return NULL;
- }
+ def)))
+ goto cleanup;
- if (qemudStartVMDaemon(conn, driver, vm, NULL) < 0) {
- virDomainRemoveInactive(&driver->domains,
- vm);
- return NULL;
- }
+ /* XXX should figure out how to release driver lock here
+ * so we don't block during startup */
+ if (qemudStartVMDaemon(conn, driver, vm, NULL) < 0)
+ goto cleanup;
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
if (dom) dom->id = vm->def->id;
+
+ virDomainUnlock(vm);
+ qemudDriverUnlock(driver);
return dom;
+
+cleanup:
+ if (vm) {
+ virDomainUnlock(vm);
+ virDomainRemoveInactive(&driver->domains,
+ vm);
+ } else {
+ virDomainDefFree(def);
+ }
+
+ qemudDriverUnlock(driver);
+ return NULL;
}
static int qemudDomainSuspend(virDomainPtr dom) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- char *info;
- virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id);
+ char *info = NULL;
+ virDomainObjPtr vm;
+
+ qemudDriverLock(driver);
+ vm = virDomainFindByID(&driver->domains, dom->id);
+ qemudDriverUnlock(driver);
+
if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no
domain with matching id %d"), dom->id);
- return -1;
+ goto cleanup;
}
if (!virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("domain is not running"));
- return -1;
+ goto cleanup;
}
- if (vm->state == VIR_DOMAIN_PAUSED)
- return 0;
- if (qemudMonitorCommand(vm, "stop", &info) < 0) {
- qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
- "%s", _("suspend operation failed"));
- return -1;
+ if (vm->state != VIR_DOMAIN_PAUSED) {
+ if (qemudMonitorCommand(vm, "stop", &info) < 0) {
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
+ "%s", _("suspend operation failed"));
+ goto cleanup;
+ }
+ vm->state = VIR_DOMAIN_PAUSED;
+ qemudDebug("Reply %s", info);
+ VIR_FREE(info);
}
- vm->state = VIR_DOMAIN_PAUSED;
- qemudDebug("Reply %s", info);
+
+ virDomainUnlock(vm);
+ return 0;
+
+cleanup:
VIR_FREE(info);
- return 0;
+ if (vm)
+ virDomainUnlock(vm);
+ return -1;
}
static int qemudDomainResume(virDomainPtr dom) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- char *info;
- virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id);
+ char *info = NULL;
+ virDomainObjPtr vm;
+
+ qemudDriverLock(driver);
+ vm = virDomainFindByID(&driver->domains, dom->id);
+ qemudDriverUnlock(driver);
+
if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
_("no domain with matching id %d"), dom->id);
- return -1;
+ goto cleanup;
}
if (!virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("domain is not running"));
- return -1;
+ goto cleanup;
}
- if (vm->state == VIR_DOMAIN_RUNNING)
- return 0;
- if (qemudMonitorCommand(vm, "cont", &info) < 0) {
- qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
- "%s", _("resume operation failed"));
- return -1;
+ if (vm->state != VIR_DOMAIN_RUNNING) {
+ if (qemudMonitorCommand(vm, "cont", &info) < 0) {
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
+ "%s", _("resume operation failed"));
+ goto cleanup;
+ }
+ vm->state = VIR_DOMAIN_RUNNING;
+ qemudDebug("Reply %s", info);
+ VIR_FREE(info);
}
- vm->state = VIR_DOMAIN_RUNNING;
- qemudDebug("Reply %s", info);
+
+ virDomainUnlock(vm);
+ return 0;
+
+cleanup:
VIR_FREE(info);
- return 0;
+ if (vm)
+ virDomainUnlock(vm);
+ return -1;
}
static int qemudDomainShutdown(virDomainPtr dom) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id);
- char* info;
+ virDomainObjPtr vm;
+ char* info = NULL;
+
+ qemudDriverLock(driver);
+ vm = virDomainFindByID(&driver->domains, dom->id);
+ qemudDriverUnlock(driver);
if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
_("no domain with matching id %d"), dom->id);
- return -1;
+ goto cleanup;
}
if (qemudMonitorCommand(vm, "system_powerdown", &info) < 0) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("shutdown operation failed"));
- return -1;
+ goto cleanup;
}
VIR_FREE(info);
+ virDomainUnlock(vm);
return 0;
+cleanup:
+ VIR_FREE(info);
+ if (vm)
+ virDomainUnlock(vm);
+ return -1;
}
static int qemudDomainDestroy(virDomainPtr dom) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id);
+ virDomainObjPtr vm;
+
+ qemudDriverLock(driver);
+ vm = virDomainFindByID(&driver->domains, dom->id);
+ qemudDriverUnlock(driver);
if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
_("no domain with matching id %d"), dom->id);
- return -1;
+ goto cleanup;
}
qemudShutdownVMDaemon(dom->conn, driver, vm);
- if (!vm->persistent)
+ if (!vm->persistent) {
+ virDomainUnlock(vm);
virDomainRemoveInactive(&driver->domains,
vm);
+ return 0;
+ }
+ virDomainUnlock(vm);
return 0;
+
+cleanup:
+ if (vm)
+ virDomainUnlock(vm);
+ return -1;
}
static char *qemudDomainGetOSType(virDomainPtr dom) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ virDomainObjPtr vm;
char *type;
+
+ qemudDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ qemudDriverUnlock(driver);
if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
"%s", _("no domain with matching uuid"));
- return NULL;
+ goto cleanup;
}
if (!(type = strdup(vm->def->os.type))) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_MEMORY,
"%s", _("failed to allocate space for
ostype"));
- return NULL;
+ goto cleanup;
}
+
+ virDomainUnlock(vm);
return type;
+
+cleanup:
+ if (vm)
+ virDomainUnlock(vm);
+ return NULL;
}
/* Returns max memory in kb, 0 if error */
static unsigned long qemudDomainGetMaxMemory(virDomainPtr dom) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ virDomainObjPtr vm;
+ unsigned long ret;
+
+ qemudDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ qemudDriverUnlock(driver);
if (!vm) {
char uuidstr[VIR_UUID_STRING_BUFLEN];
@@ -1597,15 +1751,27 @@ static unsigned long qemudDomainGetMaxMe
virUUIDFormat(dom->uuid, uuidstr);
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
_("no domain with matching uuid '%s'"),
uuidstr);
- return 0;
+ goto cleanup;
}
- return vm->def->maxmem;
+ ret = vm->def->maxmem;
+ virDomainUnlock(vm);
+
+ return ret;
+
+cleanup:
+ if (vm)
+ virDomainUnlock(vm);
+ return 0;
}
static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ virDomainObjPtr vm;
+
+ qemudDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ qemudDriverUnlock(driver);
if (!vm) {
char uuidstr[VIR_UUID_STRING_BUFLEN];
@@ -1613,22 +1779,32 @@ static int qemudDomainSetMaxMemory(virDo
virUUIDFormat(dom->uuid, uuidstr);
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
_("no domain with matching uuid '%s'"),
uuidstr);
- return -1;
+ goto cleanup;
}
if (newmax < vm->def->memory) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
"%s", _("cannot set max memory lower than current
memory"));
- return -1;
+ goto cleanup;
}
vm->def->maxmem = newmax;
+ virDomainUnlock(vm);
return 0;
+
+cleanup:
+ if (vm)
+ virDomainUnlock(vm);
+ return -1;
}
static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ virDomainObjPtr vm;
+
+ qemudDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ qemudDriverUnlock(driver);
if (!vm) {
char uuidstr[VIR_UUID_STRING_BUFLEN];
@@ -1636,33 +1812,44 @@ static int qemudDomainSetMemory(virDomai
virUUIDFormat(dom->uuid, uuidstr);
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
_("no domain with matching uuid '%s'"),
uuidstr);
- return -1;
+ goto cleanup;
}
if (virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
"%s", _("cannot set memory of an active
domain"));
- return -1;
+ goto cleanup;
}
if (newmem > vm->def->maxmem) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
"%s", _("cannot set memory higher than max
memory"));
- return -1;
+ goto cleanup;
}
vm->def->memory = newmem;
+ virDomainUnlock(vm);
return 0;
+
+cleanup:
+ if (vm)
+ virDomainUnlock(vm);
+ return -1;
}
static int qemudDomainGetInfo(virDomainPtr dom,
virDomainInfoPtr info) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ virDomainObjPtr vm;
+
+ qemudDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ qemudDriverUnlock(driver);
+
if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
"%s", _("no domain with matching uuid"));
- return -1;
+ goto cleanup;
}
info->state = vm->state;
@@ -1671,15 +1858,23 @@ static int qemudDomainGetInfo(virDomainP
info->cpuTime = 0;
} else {
if (qemudGetProcessInfo(&(info->cpuTime), vm->pid) < 0) {
- qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
("cannot read cputime for domain"));
- return -1;
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
+ _("cannot read cputime for domain"));
+ goto cleanup;
}
}
info->maxMem = vm->def->maxmem;
info->memory = vm->def->memory;
info->nrVirtCpu = vm->def->vcpus;
+
+ virDomainUnlock(vm);
return 0;
+
+cleanup:
+ if (vm)
+ virDomainUnlock(vm);
+ return -1;
}
@@ -1779,12 +1974,16 @@ static int qemudDomainSave(virDomainPtr
static int qemudDomainSave(virDomainPtr dom,
const char *path) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id);
+ virDomainObjPtr vm;
char *command, *info;
- int fd;
+ int fd = -1;
char *safe_path;
- char *xml;
+ char *xml = NULL;
struct qemud_save_header header;
+
+ qemudDriverLock(driver);
+ vm = virDomainFindByID(&driver->domains, dom->id);
+ qemudDriverUnlock(driver);
memset(&header, 0, sizeof(header));
memcpy(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic));
@@ -1793,13 +1992,13 @@ static int qemudDomainSave(virDomainPtr
if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
_("no domain with matching id %d"), dom->id);
- return -1;
+ goto cleanup;
}
if (!virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("domain is not running"));
- return -1;
+ goto cleanup;
}
/* Pause */
@@ -1808,7 +2007,7 @@ static int qemudDomainSave(virDomainPtr
if (qemudDomainSuspend(dom) != 0) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("failed to pause domain"));
- return -1;
+ goto cleanup;
}
}
@@ -1817,7 +2016,7 @@ static int qemudDomainSave(virDomainPtr
if (!xml) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("failed to get domain xml"));
- return -1;
+ goto cleanup;
}
header.xml_len = strlen(xml) + 1;
@@ -1825,24 +2024,19 @@ static int qemudDomainSave(virDomainPtr
if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
_("failed to create '%s'"), path);
- VIR_FREE(xml);
- return -1;
+ goto cleanup;
}
if (safewrite(fd, &header, sizeof(header)) != sizeof(header)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("failed to write save header"));
- close(fd);
- VIR_FREE(xml);
- return -1;
+ goto cleanup;
}
if (safewrite(fd, xml, header.xml_len) != header.xml_len) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("failed to write xml"));
- close(fd);
- VIR_FREE(xml);
- return -1;
+ goto cleanup;
}
close(fd);
@@ -1890,18 +2084,33 @@ static int qemudDomainSave(virDomainPtr
/* Shut it down */
qemudShutdownVMDaemon(dom->conn, driver, vm);
- if (!vm->persistent)
+ if (!vm->persistent) {
+ virDomainUnlock(vm);
virDomainRemoveInactive(&driver->domains,
vm);
+ return 0;
+ }
+ virDomainUnlock(vm);
return 0;
+
+cleanup:
+ if (fd != -1)
+ close(fd);
+ VIR_FREE(xml);
+ virDomainUnlock(vm);
+ return -1;
}
static int qemudDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ virDomainObjPtr vm;
int max;
+
+ qemudDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ qemudDriverUnlock(driver);
if (!vm) {
char uuidstr[VIR_UUID_STRING_BUFLEN];
@@ -1909,30 +2118,37 @@ static int qemudDomainSetVcpus(virDomain
virUUIDFormat(dom->uuid, uuidstr);
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
_("no domain with matching uuid '%s'"),
uuidstr);
- return -1;
+ goto cleanup;
}
if (virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, "%s",
_("cannot change vcpu count of an active domain"));
- return -1;
+ goto cleanup;
}
if ((max = qemudDomainGetMaxVcpus(dom)) < 0) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
"%s",
_("could not determine max vcpus for the domain"));
- return -1;
+ goto cleanup;
}
if (nvcpus > max) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
_("requested vcpus is greater than max allowable"
" vcpus for the domain: %d > %d"), nvcpus, max);
- return -1;
+ goto cleanup;
}
vm->def->vcpus = nvcpus;
+
+ virDomainUnlock(vm);
return 0;
+
+cleanup:
+ if (vm)
+ virDomainUnlock(vm);
+ return -1;
}
@@ -1943,26 +2159,39 @@ qemudDomainPinVcpu(virDomainPtr dom,
unsigned char *cpumap,
int maplen) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ virDomainObjPtr vm;
cpu_set_t mask;
int i, maxcpu;
virNodeInfo nodeinfo;
+ qemudDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ qemudDriverUnlock(driver);
+
+ if (!vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+ virUUIDFormat(dom->uuid, uuidstr);
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
+ _("no domain with matching uuid '%s'"),
uuidstr);
+ goto cleanup;
+ }
+
if (!virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
"%s",_("cannot pin vcpus on an inactive
domain"));
- return -1;
+ goto cleanup;
}
if (vcpu > (vm->nvcpupids-1)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
_("vcpu number out of range %d > %d"),
vcpu, vm->nvcpupids);
- return -1;
+ goto cleanup;
}
if (virNodeInfoPopulate(dom->conn, &nodeinfo) < 0)
- return -1;
+ goto cleanup;
maxcpu = maplen * 8;
if (maxcpu > nodeinfo.cpus)
@@ -1978,15 +2207,21 @@ qemudDomainPinVcpu(virDomainPtr dom,
if (sched_setaffinity(vm->vcpupids[vcpu], sizeof(mask), &mask) < 0) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
_("cannot set affinity: %s"), strerror(errno));
- return -1;
+ goto cleanup;
}
} else {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
"%s", _("cpu affinity is not supported"));
- return -1;
+ goto cleanup;
}
+ virDomainUnlock(vm);
return 0;
+
+cleanup:
+ if (vm)
+ virDomainUnlock(vm);
+ return -1;
}
static int
@@ -1996,18 +2231,31 @@ qemudDomainGetVcpus(virDomainPtr dom,
unsigned char *cpumaps,
int maplen) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ virDomainObjPtr vm;
virNodeInfo nodeinfo;
int i, v, maxcpu;
+
+ qemudDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ qemudDriverUnlock(driver);
+
+ if (!vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+ virUUIDFormat(dom->uuid, uuidstr);
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
+ _("no domain with matching uuid '%s'"),
uuidstr);
+ goto cleanup;
+ }
if (!virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
"%s",_("cannot pin vcpus on an inactive
domain"));
- return -1;
+ goto cleanup;
}
if (virNodeInfoPopulate(dom->conn, &nodeinfo) < 0)
- return -1;
+ goto cleanup;
maxcpu = maplen * 8;
if (maxcpu > nodeinfo.cpus)
@@ -2017,8 +2265,10 @@ qemudDomainGetVcpus(virDomainPtr dom,
if (maxinfo > vm->nvcpupids)
maxinfo = vm->nvcpupids;
- if (maxinfo < 1)
+ if (maxinfo < 1) {
+ virDomainUnlock(vm);
return 0;
+ }
if (info != NULL) {
memset(info, 0, sizeof(*info) * maxinfo);
@@ -2040,7 +2290,7 @@ qemudDomainGetVcpus(virDomainPtr dom,
if (sched_getaffinity(vm->vcpupids[v], sizeof(mask), &mask) <
0) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
_("cannot get affinity: %s"),
strerror(errno));
- return -1;
+ goto cleanup;
}
for (i = 0 ; i < maxcpu ; i++)
@@ -2050,20 +2300,30 @@ qemudDomainGetVcpus(virDomainPtr dom,
} else {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
"%s", _("cpu affinity is not
available"));
- return -1;
+ goto cleanup;
}
}
+ virDomainUnlock(vm);
return maxinfo;
+
+cleanup:
+ if (vm)
+ virDomainUnlock(vm);
+ return -1;
}
#endif /* HAVE_SCHED_GETAFFINITY */
static int qemudDomainGetMaxVcpus(virDomainPtr dom) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ virDomainObjPtr vm;
const char *type;
int ret;
+
+ qemudDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ qemudDriverUnlock(driver);
if (!vm) {
char uuidstr[VIR_UUID_STRING_BUFLEN];
@@ -2071,21 +2331,27 @@ static int qemudDomainGetMaxVcpus(virDom
virUUIDFormat(dom->uuid, uuidstr);
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
_("no domain with matching uuid '%s'"),
uuidstr);
- return -1;
+ goto cleanup;
}
if (!(type = virDomainVirtTypeToString(vm->def->virtType))) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
_("unknown virt type in domain definition
'%d'"),
vm->def->virtType);
- return -1;
+ goto cleanup;
}
if ((ret = qemudGetMaxVCPUs(dom->conn, type)) < 0) {
- return -1;
+ goto cleanup;
}
+ virDomainUnlock(vm);
return ret;
+
+cleanup:
+ if (vm)
+ virDomainUnlock(vm);
+ return -1;
}
@@ -2093,10 +2359,10 @@ static int qemudDomainRestore(virConnect
const char *path) {
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
virDomainDefPtr def;
- virDomainObjPtr vm;
- int fd;
+ virDomainObjPtr vm = NULL;
+ int fd = -1;
int ret;
- char *xml;
+ char *xml = NULL;
struct qemud_save_header header;
/* Verify the header and read the XML */
@@ -2143,13 +2409,14 @@ static int qemudDomainRestore(virConnect
return -1;
}
+
+ qemudDriverLock(driver);
+
/* Create a domain from this XML */
if (!(def = virDomainDefParseString(conn, driver->caps, xml))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("failed to parse XML"));
- close(fd);
- VIR_FREE(xml);
- return -1;
+ goto cleanup;
}
VIR_FREE(xml);
@@ -2160,9 +2427,10 @@ static int qemudDomainRestore(virConnect
if (vm && virDomainIsActive(vm)) {
qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
_("domain is already active as '%s'"),
vm->def->name);
- close(fd);
- return -1;
+ goto cleanup;
}
+ if (vm)
+ virDomainUnlock(vm);
if (!(vm = virDomainAssignDef(conn,
&driver->domains,
@@ -2170,22 +2438,25 @@ static int qemudDomainRestore(virConnect
qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("failed to assign new VM"));
virDomainDefFree(def);
- close(fd);
- return -1;
+ goto cleanup;
}
/* Set the migration source and start it up. */
vm->stdin_fd = fd;
ret = qemudStartVMDaemon(conn, driver, vm, "stdio");
close(fd);
+ fd = -1;
vm->stdin_fd = -1;
if (ret < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("failed to start VM"));
- if (!vm->persistent)
+ if (!vm->persistent) {
+ virDomainUnlock(vm);
virDomainRemoveInactive(&driver->domains,
vm);
- return -1;
+ vm = NULL;
+ }
+ goto cleanup;
}
/* If it was running before, resume it now. */
@@ -2194,30 +2465,57 @@ static int qemudDomainRestore(virConnect
if (qemudMonitorCommand(vm, "cont", &info) < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("failed to resume domain"));
- return -1;
+ goto cleanup;
}
VIR_FREE(info);
vm->state = VIR_DOMAIN_RUNNING;
}
+ virDomainUnlock(vm);
+ qemudDriverUnlock(driver);
return 0;
+
+cleanup:
+ if (fd != -1)
+ close(fd);
+ VIR_FREE(xml);
+ if (vm)
+ virDomainUnlock(vm);
+ qemudDriverUnlock(driver);
+ return -1;
}
static char *qemudDomainDumpXML(virDomainPtr dom,
int flags ATTRIBUTE_UNUSED) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ virDomainObjPtr vm;
+ char *ret;
+
+ qemudDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ qemudDriverUnlock(driver);
+
if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
"%s", _("no domain with matching uuid"));
- return NULL;
+ goto cleanup;
}
- return virDomainDefFormat(dom->conn,
- (flags & VIR_DOMAIN_XML_INACTIVE) &&
vm->newDef ?
- vm->newDef : vm->def,
- flags);
+ ret = virDomainDefFormat(dom->conn,
+ (flags & VIR_DOMAIN_XML_INACTIVE) &&
vm->newDef ?
+ vm->newDef : vm->def,
+ flags);
+ if (!ret)
+ goto cleanup;
+
+ virDomainUnlock(vm);
+ return ret;
+
+cleanup:
+ if (vm)
+ virDomainUnlock(vm);
+ return NULL;
}
@@ -2226,15 +2524,20 @@ static int qemudListDefinedDomains(virCo
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
int got = 0, i;
+ qemudDriverLock(driver);
for (i = 0 ; i < driver->domains.count && got < nnames ; i++) {
+ virDomainLock(driver->domains.objs[i]);
if (!virDomainIsActive(driver->domains.objs[i])) {
if (!(names[got++] = strdup(driver->domains.objs[i]->def->name))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
"%s", _("failed to allocate space for VM
name string"));
+ virDomainUnlock(driver->domains.objs[i]);
goto cleanup;
}
}
+ virDomainUnlock(driver->domains.objs[i]);
}
+ qemudDriverUnlock(driver);
return got;
@@ -2248,9 +2551,14 @@ static int qemudNumDefinedDomains(virCon
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
int n = 0, i;
- for (i = 0 ; i < driver->domains.count ; i++)
+ qemudDriverLock(driver);
+ for (i = 0 ; i < driver->domains.count ; i++) {
+ virDomainLock(driver->domains.objs[i]);
if (!virDomainIsActive(driver->domains.objs[i]))
n++;
+ virDomainUnlock(driver->domains.objs[i]);
+ }
+ qemudDriverUnlock(driver);
return n;
}
@@ -2258,77 +2566,110 @@ static int qemudNumDefinedDomains(virCon
static int qemudDomainStart(virDomainPtr dom) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ virDomainObjPtr vm;
+ int ret;
+
+ qemudDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
"%s", _("no domain with matching uuid"));
+ qemudDriverUnlock(driver);
return -1;
}
- return qemudStartVMDaemon(dom->conn, driver, vm, NULL);
+ ret = qemudStartVMDaemon(dom->conn, driver, vm, NULL);
+ virDomainUnlock(vm);
+ qemudDriverUnlock(driver);
+ return ret;
}
static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
virDomainDefPtr def;
- virDomainObjPtr vm;
+ virDomainObjPtr vm = NULL;
virDomainPtr dom;
+ qemudDriverLock(driver);
+
if (!(def = virDomainDefParseString(conn, driver->caps, xml)))
- return NULL;
+ goto cleanup;
if (!(vm = virDomainAssignDef(conn,
&driver->domains,
def))) {
virDomainDefFree(def);
- return NULL;
+ goto cleanup;
}
vm->persistent = 1;
if (virDomainSaveConfig(conn,
driver->configDir,
vm->newDef ? vm->newDef : vm->def) < 0) {
+ virDomainUnlock(vm);
virDomainRemoveInactive(&driver->domains,
vm);
- return NULL;
+ vm = NULL;
+ goto cleanup;
}
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
if (dom) dom->id = vm->def->id;
+
+ virDomainUnlock(vm);
+ qemudDriverUnlock(driver);
return dom;
+
+cleanup:
+ if (vm)
+ virDomainUnlock(vm);
+ qemudDriverUnlock(driver);
+ return NULL;
}
static int qemudDomainUndefine(virDomainPtr dom) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ virDomainObjPtr vm = NULL;
+
+ qemudDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
"%s", _("no domain with matching uuid"));
- return -1;
+ goto cleanup;
}
if (virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("cannot delete active domain"));
- return -1;
+ goto cleanup;
}
if (!vm->persistent) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("cannot undefine transient
domain"));
- return -1;
+ goto cleanup;
}
if (virDomainDeleteConfig(dom->conn, driver->configDir,
driver->autostartDir, vm) < 0)
- return -1;
+ goto cleanup;
+ virDomainUnlock(vm);
virDomainRemoveInactive(&driver->domains,
vm);
+ qemudDriverUnlock(driver);
+
return 0;
+
+cleanup:
+ if (vm)
+ virDomainUnlock(vm);
+ qemudDriverLock(driver);
+ return -1;
}
/* Return the disks name for use in monitor commands */
@@ -2681,9 +3022,13 @@ static int qemudDomainAttachDevice(virDo
static int qemudDomainAttachDevice(virDomainPtr dom,
const char *xml) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ virDomainObjPtr vm;
virDomainDeviceDefPtr dev;
int ret = 0, supported = 0;
+
+ qemudDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ qemudDriverUnlock(driver);
if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
@@ -2694,13 +3039,11 @@ static int qemudDomainAttachDevice(virDo
if (!virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("cannot attach device on inactive
domain"));
- return -1;
+ goto cleanup;
}
- dev = virDomainDeviceDefParse(dom->conn, vm->def, xml);
- if (dev == NULL) {
- return -1;
- }
+ if (!(dev = virDomainDeviceDefParse(dom->conn, vm->def, xml)))
+ goto cleanup;
if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
switch (dev->data.disk->device) {
@@ -2723,8 +3066,8 @@ static int qemudDomainAttachDevice(virDo
} else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV &&
dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
dev->data.hostdev->source.subsys.type ==
VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
- supported = 1;
- ret = qemudDomainAttachHostDevice(dom, dev);
+ supported = 1;
+ ret = qemudDomainAttachHostDevice(dom, dev);
}
if (!supported) {
@@ -2734,13 +3077,24 @@ static int qemudDomainAttachDevice(virDo
}
VIR_FREE(dev);
+
+ virDomainUnlock(vm);
return ret;
+
+cleanup:
+ if (vm)
+ virDomainUnlock(vm);
+ return -1;
}
static int qemudDomainGetAutostart(virDomainPtr dom,
int *autostart) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ virDomainObjPtr vm;
+
+ qemudDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ qemudDriverUnlock(driver);
if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
@@ -2750,71 +3104,80 @@ static int qemudDomainGetAutostart(virDo
*autostart = vm->autostart;
+ virDomainUnlock(vm);
return 0;
}
static int qemudDomainSetAutostart(virDomainPtr dom,
int autostart) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ virDomainObjPtr vm;
char *configFile = NULL, *autostartLink = NULL;
- int ret = -1;
+
+ qemudDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ qemudDriverUnlock(driver);
if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
"%s", _("no domain with matching uuid"));
- return -1;
+ goto cleanup;
}
if (!vm->persistent) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("cannot set autostart for transient
domain"));
- return -1;
+ goto cleanup;
}
autostart = (autostart != 0);
- if (vm->autostart == autostart)
- return 0;
+ if (vm->autostart != autostart) {
+ if ((configFile = virDomainConfigFile(dom->conn, driver->configDir,
vm->def->name)) == NULL)
+ goto cleanup;
+ if ((autostartLink = virDomainConfigFile(dom->conn, driver->autostartDir,
vm->def->name)) == NULL)
+ goto cleanup;
- if ((configFile = virDomainConfigFile(dom->conn, driver->configDir,
vm->def->name)) == NULL)
- goto cleanup;
- if ((autostartLink = virDomainConfigFile(dom->conn, driver->autostartDir,
vm->def->name)) == NULL)
- goto cleanup;
+ if (autostart) {
+ int err;
- if (autostart) {
- int err;
+ if ((err = virFileMakePath(driver->autostartDir))) {
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
+ _("cannot create autostart directory %s:
%s"),
+ driver->autostartDir, strerror(err));
+ goto cleanup;
+ }
- if ((err = virFileMakePath(driver->autostartDir))) {
- qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
- _("cannot create autostart directory %s: %s"),
- driver->autostartDir, strerror(err));
- goto cleanup;
+ if (symlink(configFile, autostartLink) < 0) {
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
+ _("Failed to create symlink '%s to
'%s': %s"),
+ autostartLink, configFile, strerror(errno));
+ goto cleanup;
+ }
+ } else {
+ if (unlink(autostartLink) < 0 && errno != ENOENT && errno
!= ENOTDIR) {
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
+ _("Failed to delete symlink '%s':
%s"),
+ autostartLink, strerror(errno));
+ goto cleanup;
+ }
}
- if (symlink(configFile, autostartLink) < 0) {
- qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
- _("Failed to create symlink '%s to '%s':
%s"),
- autostartLink, configFile, strerror(errno));
- goto cleanup;
- }
- } else {
- if (unlink(autostartLink) < 0 && errno != ENOENT && errno !=
ENOTDIR) {
- qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
- _("Failed to delete symlink '%s': %s"),
- autostartLink, strerror(errno));
- goto cleanup;
- }
+ vm->autostart = autostart;
}
- vm->autostart = autostart;
- ret = 0;
+ VIR_FREE(configFile);
+ VIR_FREE(autostartLink);
+ virDomainUnlock(vm);
+ return 0;
cleanup:
+ if (vm)
+ virDomainUnlock(vm);
VIR_FREE(configFile);
VIR_FREE(autostartLink);
- return ret;
+ return -1;
}
/* This uses the 'info blockstats' monitor command which was
@@ -2833,8 +3196,12 @@ qemudDomainBlockStats (virDomainPtr dom,
const char *qemu_dev_name = NULL;
size_t len;
int i, ret = -1;
- const virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id);
+ virDomainObjPtr vm;
virDomainDiskDefPtr disk = NULL;
+
+ qemudDriverLock(driver);
+ vm = virDomainFindByID(&driver->domains, dom->id);
+ qemudDriverUnlock(driver);
if (!vm) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
@@ -2844,7 +3211,7 @@ qemudDomainBlockStats (virDomainPtr dom,
if (!virDomainIsActive (vm)) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("domain is not running"));
- return -1;
+ goto cleanup;
}
for (i = 0 ; i < vm->def->ndisks ; i++) {
@@ -2857,7 +3224,7 @@ qemudDomainBlockStats (virDomainPtr dom,
if (!disk) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
_("invalid path: %s"), path);
- return -1;
+ goto cleanup;
}
qemu_dev_name = qemudDiskDeviceName(dom, disk);
@@ -2868,7 +3235,7 @@ qemudDomainBlockStats (virDomainPtr dom,
if (qemudMonitorCommand (vm, "info blockstats", &info) < 0) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("'info blockstats' command
failed"));
- goto out;
+ goto cleanup;
}
DEBUG ("info blockstats reply: %s", info);
@@ -2881,7 +3248,7 @@ qemudDomainBlockStats (virDomainPtr dom,
qemudReportError (dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
"%s",
_("'info blockstats' not supported by this
qemu"));
- goto out;
+ goto cleanup;
}
stats->rd_req = -1;
@@ -2933,7 +3300,7 @@ qemudDomainBlockStats (virDomainPtr dom,
p++;
}
ret = 0;
- goto out;
+ goto done;
}
/* Skip to next line. */
@@ -2945,10 +3312,20 @@ qemudDomainBlockStats (virDomainPtr dom,
/* If we reach here then the device was not found. */
qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
_("device not found: %s (%s)"), path, qemu_dev_name);
- out:
+ goto cleanup;
+
+ done:
VIR_FREE(qemu_dev_name);
VIR_FREE(info);
- return ret;
+ virDomainUnlock(vm);
+ return 0;
+
+cleanup:
+ VIR_FREE(qemu_dev_name);
+ VIR_FREE(info);
+ if (vm)
+ virDomainUnlock(vm);
+ return -1;
}
static int
@@ -2958,25 +3335,29 @@ qemudDomainInterfaceStats (virDomainPtr
{
#ifdef __linux__
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id);
- int i;
+ virDomainObjPtr vm;
+ int i, ret;
+
+ qemudDriverLock(driver);
+ vm = virDomainFindByID(&driver->domains, dom->id);
+ qemudDriverUnlock(driver);
if (!vm) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
_("no domain with matching id %d"), dom->id);
- return -1;
+ goto cleanup;
}
if (!virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("domain is not running"));
- return -1;
+ goto cleanup;
}
if (!path || path[0] == '\0') {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
"%s", _("NULL or empty path"));
- return -1;
+ goto cleanup;
}
/* Check the path is one of the domain's network interfaces. */
@@ -2988,10 +3369,17 @@ qemudDomainInterfaceStats (virDomainPtr
qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
_("invalid path, '%s' is not a known interface"),
path);
+ goto cleanup;
+
+ ok:
+ ret = linuxDomainInterfaceStats (dom->conn, path, stats);
+ virDomainUnlock(vm);
+ return ret;
+
+cleanup:
+ if (vm)
+ virDomainUnlock(vm);
return -1;
- ok:
-
- return linuxDomainInterfaceStats (dom->conn, path, stats);
#else
qemudReportError (dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
"%s", __FUNCTION__);
@@ -3007,19 +3395,23 @@ qemudDomainBlockPeek (virDomainPtr dom,
unsigned int flags ATTRIBUTE_UNUSED)
{
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ virDomainObjPtr vm;
int fd, ret = -1, i;
+
+ qemudDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ qemudDriverUnlock(driver);
if (!vm) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
"%s", _("no domain with matching uuid"));
- return -1;
+ goto cleanup;
}
if (!path || path[0] == '\0') {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
"%s", _("NULL or empty path"));
- return -1;
+ goto cleanup;
}
/* Check the path belongs to this domain. */
@@ -3030,7 +3422,7 @@ qemudDomainBlockPeek (virDomainPtr dom,
}
qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
"%s", _("invalid path"));
- return -1;
+ goto cleanup;
found:
/* The path is correct, now try to open it and get its size. */
@@ -3055,7 +3447,14 @@ found:
ret = 0;
done:
if (fd >= 0) close (fd);
+
+ virDomainUnlock(vm);
return ret;
+
+cleanup:
+ if (vm)
+ virDomainUnlock(vm);
+ return -1;
}
static int
@@ -3065,34 +3464,38 @@ qemudDomainMemoryPeek (virDomainPtr dom,
unsigned int flags)
{
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
- virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id);
+ virDomainObjPtr vm;
char cmd[256], *info;
char tmp[] = TEMPDIR "/qemu.mem.XXXXXX";
int fd = -1, ret = -1;
+ qemudDriverLock(driver);
+ vm = virDomainFindByID(&driver->domains, dom->id);
+ qemudDriverUnlock(driver);
+
if (flags != VIR_MEMORY_VIRTUAL) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
"%s", _("QEMU driver only supports virtual
memory addrs"));
- return -1;
+ goto cleanup;
}
if (!vm) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
_("no domain with matching id %d"), dom->id);
- return -1;
+ goto cleanup;
}
if (!virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("domain is not running"));
- return -1;
+ goto cleanup;
}
/* Create a temporary filename. */
if ((fd = mkstemp (tmp)) == -1) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_SYSTEM_ERROR,
"%s", strerror (errno));
- return -1;
+ goto cleanup;
}
/* Issue the memsave command. */
@@ -3104,7 +3507,7 @@ qemudDomainMemoryPeek (virDomainPtr dom,
}
DEBUG ("memsave reply: %s", info);
- free (info);
+ VIR_FREE(info);
/* Read the memory file into buffer. */
if (saferead (fd, buffer, size) == (ssize_t) -1) {
@@ -3117,7 +3520,13 @@ done:
done:
if (fd >= 0) close (fd);
unlink (tmp);
+ virDomainUnlock(vm);
return ret;
+
+cleanup:
+ if (vm)
+ virDomainUnlock(vm);
+ return -1;
}
--
|: Red Hat, Engineering, London -o-
http://people.redhat.com/berrange/ :|
|:
http://libvirt.org -o-
http://virt-manager.org -o-
http://ovirt.org :|
|:
http://autobuild.org -o-
http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|