]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Add locking for (nearly complete) thread safety to QEMU driver
authorDaniel P. Berrange <berrange@redhat.com>
Thu, 4 Dec 2008 21:06:41 +0000 (21:06 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Thu, 4 Dec 2008 21:06:41 +0000 (21:06 +0000)
ChangeLog
src/qemu_conf.h
src/qemu_driver.c

index 41e333794c69f7216ad487f32900ffeac40d8dea..43d1410b6b8832e211e596ac414a717bba292224 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Thu Dec  4 21:05:41 GMT 2008 Daniel P. Berrange <berrange@redhat.com>
+
+       * src/qemu_conf.h: Add a driver lock variable
+       * src/qemu_driver.c: Add locking for thread safety
+
 Thu Dec  4 21:01:41 GMT 2008 Daniel P. Berrange <berrange@redhat.com>
 
        * src/qemu_driver.c: Merge all return paths from driver APIs
index 6b2acade1c06cf0d5d82db1d0d4ae68161f768d4..58ea321b45c205763502e2a6c1d49b29f1210b93 100644 (file)
@@ -51,6 +51,8 @@ enum qemud_cmd_flags {
 
 /* Main driver state */
 struct qemud_driver {
+    PTHREAD_MUTEX_T(lock);
+
     unsigned int qemuVersion;
     int nextvmid;
 
index 32e46e0794e900691c567d3a996f8d5397546a5d..cc7b6c0368a7e6361115192853f8d47dbb7f722e 100644 (file)
@@ -76,6 +76,15 @@ static int qemudShutdown(void);
 
 #define qemudLog(level, msg...) fprintf(stderr, msg)
 
+static void qemuDriverLock(struct qemud_driver *driver)
+{
+    pthread_mutex_lock(&driver->lock);
+}
+static void qemuDriverUnlock(struct qemud_driver *driver)
+{
+    pthread_mutex_unlock(&driver->lock);
+}
+
 static int qemudSetCloseExec(int fd) {
     int flags;
     if ((flags = fcntl(fd, F_GETFD)) < 0)
@@ -141,6 +150,7 @@ qemudAutostartConfigs(struct qemud_driver *driver) {
 
     for (i = 0 ; i < driver->domains.count ; i++) {
         virDomainObjPtr vm = driver->domains.objs[i];
+        virDomainObjLock(vm);
         if (vm->autostart &&
             !virDomainIsActive(vm)) {
             int ret = qemudStartVMDaemon(NULL, driver, vm, NULL);
@@ -154,6 +164,7 @@ qemudAutostartConfigs(struct qemud_driver *driver) {
                                          VIR_DOMAIN_EVENT_STARTED_BOOTED);
             }
         }
+        virDomainObjUnlock(vm);
     }
 }
 
@@ -172,12 +183,15 @@ qemudStartup(void) {
     if (VIR_ALLOC(qemu_driver) < 0)
         return -1;
 
+    pthread_mutex_init(&qemu_driver->lock, NULL);
+    qemuDriverLock(qemu_driver);
+
     /* Don't have a dom0 so start from 1 */
     qemu_driver->nextvmid = 1;
 
     /* Init callback list */
     if(VIR_ALLOC(qemu_driver->domainEventCallbacks) < 0)
-        return -1;
+        goto out_of_memory;
 
     if (!uid) {
         if (asprintf(&qemu_driver->logDir,
@@ -190,7 +204,7 @@ qemudStartup(void) {
         if (!(pw = getpwuid(uid))) {
             qemudLog(QEMUD_ERR, _("Failed to find user record for uid '%d': %s\n"),
                      uid, strerror(errno));
-            goto out_nouid;
+            goto error;
         }
 
         if (asprintf(&qemu_driver->logDir,
@@ -220,8 +234,7 @@ qemudStartup(void) {
         goto out_of_memory;
 
     if (qemudLoadDriverConfig(qemu_driver, driverConf) < 0) {
-        qemudShutdown();
-        return -1;
+        goto error;
     }
 
     if (virDomainLoadAllConfigs(NULL,
@@ -229,20 +242,22 @@ qemudStartup(void) {
                                 &qemu_driver->domains,
                                 qemu_driver->configDir,
                                 qemu_driver->autostartDir,
-                                NULL, NULL) < 0) {
-        qemudShutdown();
-        return -1;
-    }
+                                NULL, NULL) < 0)
+        goto error;
     qemudAutostartConfigs(qemu_driver);
 
+    qemuDriverUnlock(qemu_driver);
+
     return 0;
 
- out_of_memory:
+out_of_memory:
     qemudLog (QEMUD_ERR,
               "%s", _("qemudStartup: out of memory\n"));
- out_nouid:
+error:
+    if (qemu_driver)
+        qemuDriverUnlock(qemu_driver);
     VIR_FREE(base);
-    VIR_FREE(qemu_driver);
+    qemudShutdown();
     return -1;
 }
 
@@ -267,6 +282,7 @@ qemudReload(void) {
     if (!qemu_driver)
         return 0;
 
+    qemuDriverLock(qemu_driver);
     virDomainLoadAllConfigs(NULL,
                             qemu_driver->caps,
                             &qemu_driver->domains,
@@ -275,6 +291,7 @@ qemudReload(void) {
                             qemudNotifyLoadDomain, qemu_driver);
 
     qemudAutostartConfigs(qemu_driver);
+    qemuDriverUnlock(qemu_driver);
 
     return 0;
 }
@@ -290,16 +307,22 @@ qemudReload(void) {
 static int
 qemudActive(void) {
     unsigned int i;
+    int active = 0;
 
     if (!qemu_driver)
         return 0;
 
-    for (i = 0 ; i < qemu_driver->domains.count ; i++)
-        if (virDomainIsActive(qemu_driver->domains.objs[i]))
-            return 1;
+    qemuDriverLock(qemu_driver);
+    for (i = 0 ; i < qemu_driver->domains.count ; i++) {
+        virDomainObjPtr vm = qemu_driver->domains.objs[i];
+        virDomainObjLock(vm);
+        if (virDomainIsActive(vm))
+            active = 1;
+        virDomainObjUnlock(vm);
+    }
 
-    /* Otherwise we're happy to deal with a shutdown */
-    return 0;
+    qemuDriverUnlock(qemu_driver);
+    return active;
 }
 
 /**
@@ -314,16 +337,16 @@ qemudShutdown(void) {
     if (!qemu_driver)
         return -1;
 
+    qemuDriverLock(qemu_driver);
     virCapabilitiesFree(qemu_driver->caps);
 
     /* shutdown active VMs */
     for (i = 0 ; i < qemu_driver->domains.count ; i++) {
         virDomainObjPtr dom = qemu_driver->domains.objs[i];
+        virDomainObjLock(dom);
         if (virDomainIsActive(dom))
             qemudShutdownVMDaemon(NULL, qemu_driver, dom);
-        if (!dom->persistent)
-            virDomainRemoveInactive(&qemu_driver->domains,
-                                    dom);
+        virDomainObjUnlock(dom);
     }
 
     virDomainObjListFree(&qemu_driver->domains);
@@ -340,6 +363,7 @@ qemudShutdown(void) {
     if (qemu_driver->brctl)
         brShutdown(qemu_driver->brctl);
 
+    qemuDriverUnlock(qemu_driver);
     VIR_FREE(qemu_driver);
 
     return 0;
@@ -1046,60 +1070,60 @@ static void qemudShutdownVMDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
     }
 }
 
-static int qemudDispatchVMLog(struct qemud_driver *driver, virDomainObjPtr vm, int fd) {
-    if (qemudVMData(driver, vm, fd) < 0) {
-        qemudShutdownVMDaemon(NULL, driver, vm);
-        qemudDomainEventDispatch(driver, vm,
-                                 VIR_DOMAIN_EVENT_STOPPED,
-                                 VIR_DOMAIN_EVENT_STOPPED_FAILED);
-        if (!vm->persistent)
-            virDomainRemoveInactive(&driver->domains,
-                                    vm);
-    }
-    return 0;
-}
-
-static int qemudDispatchVMFailure(struct qemud_driver *driver, virDomainObjPtr vm,
-                                  int fd ATTRIBUTE_UNUSED) {
-    qemudShutdownVMDaemon(NULL, driver, vm);
-    qemudDomainEventDispatch(driver, vm,
-                             VIR_DOMAIN_EVENT_STOPPED,
-                             VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
-    if (!vm->persistent)
-        virDomainRemoveInactive(&driver->domains,
-                                vm);
-    return 0;
-}
-
 
 static void
 qemudDispatchVMEvent(int watch, int fd, int events, void *opaque) {
     struct qemud_driver *driver = opaque;
     virDomainObjPtr vm = NULL;
     unsigned int i;
+    int quit = 0, failed = 0;
 
+    qemuDriverLock(driver);
     for (i = 0 ; i < driver->domains.count ; i++) {
-        if (virDomainIsActive(driver->domains.objs[i]) &&
-            (driver->domains.objs[i]->stdout_watch == watch ||
-             driver->domains.objs[i]->stderr_watch == watch)) {
-            vm = driver->domains.objs[i];
+        virDomainObjPtr tmpvm = driver->domains.objs[i];
+        virDomainObjLock(tmpvm);
+        if (virDomainIsActive(tmpvm) &&
+            (tmpvm->stdout_watch == watch ||
+             tmpvm->stderr_watch == watch)) {
+            vm = tmpvm;
             break;
         }
+        virDomainObjUnlock(tmpvm);
     }
 
     if (!vm)
-        return;
+        goto cleanup;
 
     if (vm->stdout_fd != fd &&
         vm->stderr_fd != fd) {
-        qemudDispatchVMFailure(driver, vm, fd);
-        return;
+        failed = 1;
+    } else {
+        if (events & VIR_EVENT_HANDLE_READABLE) {
+            if (qemudVMData(driver, vm, fd) < 0)
+                failed = 1;
+        } else {
+            quit = 1;
+        }
     }
 
-    if (events == VIR_EVENT_HANDLE_READABLE)
-        qemudDispatchVMLog(driver, vm, fd);
-    else
-        qemudDispatchVMFailure(driver, vm, fd);
+    if (failed || quit) {
+        qemudShutdownVMDaemon(NULL, driver, vm);
+        qemudDomainEventDispatch(driver, vm,
+                                 VIR_DOMAIN_EVENT_STOPPED,
+                                 quit ?
+                                 VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN :
+                                 VIR_DOMAIN_EVENT_STOPPED_FAILED);
+        if (!vm->persistent) {
+            virDomainRemoveInactive(&driver->domains,
+                                    vm);
+            vm = NULL;
+        }
+    }
+
+cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    qemuDriverUnlock(driver);
 }
 
 static int
@@ -1311,9 +1335,11 @@ static char *qemudGetCapabilities(virConnectPtr conn) {
     struct qemud_driver *driver = conn->privateData;
     char *xml;
 
+    qemuDriverLock(driver);
     if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL)
         qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
                  "%s", _("failed to allocate space for capabilities support"));
+    qemuDriverUnlock(driver);
 
     return xml;
 }
@@ -1423,7 +1449,9 @@ static virDomainPtr qemudDomainLookupByID(virConnectPtr conn,
     virDomainObjPtr vm;
     virDomainPtr dom = NULL;
 
+    qemuDriverLock(driver);
     vm  = virDomainFindByID(&driver->domains, id);
+    qemuDriverUnlock(driver);
 
     if (!vm) {
         qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
@@ -1434,15 +1462,21 @@ static virDomainPtr qemudDomainLookupByID(virConnectPtr conn,
     if (dom) dom->id = vm->def->id;
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return dom;
 }
+
 static virDomainPtr qemudDomainLookupByUUID(virConnectPtr conn,
                                             const unsigned char *uuid) {
     struct qemud_driver *driver = conn->privateData;
     virDomainObjPtr vm;
     virDomainPtr dom = NULL;
 
+    qemuDriverLock(driver);
     vm = virDomainFindByUUID(&driver->domains, uuid);
+    qemuDriverUnlock(driver);
+
     if (!vm) {
         qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
         goto cleanup;
@@ -1452,15 +1486,21 @@ static virDomainPtr qemudDomainLookupByUUID(virConnectPtr conn,
     if (dom) dom->id = vm->def->id;
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return dom;
 }
+
 static virDomainPtr qemudDomainLookupByName(virConnectPtr conn,
                                             const char *name) {
     struct qemud_driver *driver = conn->privateData;
     virDomainObjPtr vm;
     virDomainPtr dom = NULL;
 
+    qemuDriverLock(driver);
     vm = virDomainFindByName(&driver->domains, name);
+    qemuDriverUnlock(driver);
+
     if (!vm) {
         qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
         goto cleanup;
@@ -1470,6 +1510,8 @@ static virDomainPtr qemudDomainLookupByName(virConnectPtr conn,
     if (dom) dom->id = vm->def->id;
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return dom;
 }
 
@@ -1477,6 +1519,7 @@ static int qemudGetVersion(virConnectPtr conn, unsigned long *version) {
     struct qemud_driver *driver = conn->privateData;
     int ret = -1;
 
+    qemuDriverLock(driver);
     if (qemudExtractVersion(conn, driver) < 0)
         goto cleanup;
 
@@ -1484,6 +1527,7 @@ static int qemudGetVersion(virConnectPtr conn, unsigned long *version) {
     ret = 0;
 
 cleanup:
+    qemuDriverUnlock(driver);
     return ret;
 }
 
@@ -1513,29 +1557,42 @@ static int qemudListDomains(virConnectPtr conn, int *ids, int nids) {
     struct qemud_driver *driver = conn->privateData;
     int got = 0, i;
 
-    for (i = 0 ; i < driver->domains.count && got < nids ; i++)
+    qemuDriverLock(driver);
+    for (i = 0 ; i < driver->domains.count && got < nids ; i++) {
+        virDomainObjLock(driver->domains.objs[i]);
         if (virDomainIsActive(driver->domains.objs[i]))
             ids[got++] = driver->domains.objs[i]->def->id;
+        virDomainObjUnlock(driver->domains.objs[i]);
+    }
+    qemuDriverUnlock(driver);
 
     return got;
 }
+
 static int qemudNumDomains(virConnectPtr conn) {
     struct qemud_driver *driver = conn->privateData;
     int n = 0, i;
 
-    for (i = 0 ; i < driver->domains.count ; i++)
+    qemuDriverLock(driver);
+    for (i = 0 ; i < driver->domains.count ; i++) {
+        virDomainObjLock(driver->domains.objs[i]);
         if (virDomainIsActive(driver->domains.objs[i]))
             n++;
+        virDomainObjUnlock(driver->domains.objs[i]);
+    }
+    qemuDriverUnlock(driver);
 
     return n;
 }
+
 static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
                                       unsigned int flags ATTRIBUTE_UNUSED) {
     struct qemud_driver *driver = conn->privateData;
     virDomainDefPtr def;
-    virDomainObjPtr vm;
+    virDomainObjPtr vm = NULL;
     virDomainPtr dom = NULL;
 
+    qemuDriverLock(driver);
     if (!(def = virDomainDefParseString(conn, driver->caps, xml)))
         goto cleanup;
 
@@ -1567,6 +1624,7 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
     if (qemudStartVMDaemon(conn, driver, vm, NULL) < 0) {
         virDomainRemoveInactive(&driver->domains,
                                 vm);
+        vm = NULL;
         goto cleanup;
     }
     qemudDomainEventDispatch(driver, vm,
@@ -1578,7 +1636,9 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
 
 cleanup:
     virDomainDefFree(def);
-
+    if (vm)
+        virDomainObjUnlock(vm);
+    qemuDriverUnlock(driver);
     return dom;
 }
 
@@ -1589,7 +1649,10 @@ static int qemudDomainSuspend(virDomainPtr dom) {
     virDomainObjPtr vm;
     int ret = -1;
 
+    qemuDriverLock(driver);
     vm = virDomainFindByID(&driver->domains, dom->id);
+    qemuDriverUnlock(driver);
+
     if (!vm) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching id %d"), dom->id);
         goto cleanup;
@@ -1615,6 +1678,8 @@ static int qemudDomainSuspend(virDomainPtr dom) {
     ret = 0;
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -1625,7 +1690,10 @@ static int qemudDomainResume(virDomainPtr dom) {
     virDomainObjPtr vm;
     int ret = -1;
 
+    qemuDriverLock(driver);
     vm = virDomainFindByID(&driver->domains, dom->id);
+    qemuDriverUnlock(driver);
+
     if (!vm) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                          _("no domain with matching id %d"), dom->id);
@@ -1652,6 +1720,8 @@ static int qemudDomainResume(virDomainPtr dom) {
     ret = 0;
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -1662,7 +1732,10 @@ static int qemudDomainShutdown(virDomainPtr dom) {
     char* info;
     int ret = -1;
 
+    qemuDriverLock(driver);
     vm = virDomainFindByID(&driver->domains, dom->id);
+    qemuDriverUnlock(driver);
+
     if (!vm) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                          _("no domain with matching id %d"), dom->id);
@@ -1678,8 +1751,9 @@ static int qemudDomainShutdown(virDomainPtr dom) {
     ret = 0;
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
-
 }
 
 
@@ -1688,6 +1762,7 @@ static int qemudDomainDestroy(virDomainPtr dom) {
     virDomainObjPtr vm;
     int ret = -1;
 
+    qemuDriverLock(driver);
     vm  = virDomainFindByID(&driver->domains, dom->id);
     if (!vm) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
@@ -1699,12 +1774,17 @@ static int qemudDomainDestroy(virDomainPtr dom) {
     qemudDomainEventDispatch(driver, vm,
                              VIR_DOMAIN_EVENT_STOPPED,
                              VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
-    if (!vm->persistent)
+    if (!vm->persistent) {
         virDomainRemoveInactive(&driver->domains,
                                 vm);
+        vm = NULL;
+    }
     ret = 0;
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    qemuDriverUnlock(driver);
     return ret;
 }
 
@@ -1714,7 +1794,9 @@ static char *qemudDomainGetOSType(virDomainPtr dom) {
     virDomainObjPtr vm;
     char *type = NULL;
 
+    qemuDriverLock(driver);
     vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    qemuDriverUnlock(driver);
     if (!vm) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                          "%s", _("no domain with matching uuid"));
@@ -1726,6 +1808,8 @@ static char *qemudDomainGetOSType(virDomainPtr dom) {
                          "%s", _("failed to allocate space for ostype"));
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return type;
 }
 
@@ -1735,7 +1819,10 @@ static unsigned long qemudDomainGetMaxMemory(virDomainPtr dom) {
     virDomainObjPtr vm;
     unsigned long ret = 0;
 
+    qemuDriverLock(driver);
     vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    qemuDriverUnlock(driver);
+
     if (!vm) {
         char uuidstr[VIR_UUID_STRING_BUFLEN];
 
@@ -1748,6 +1835,8 @@ static unsigned long qemudDomainGetMaxMemory(virDomainPtr dom) {
     ret = vm->def->maxmem;
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -1756,7 +1845,10 @@ static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) {
     virDomainObjPtr vm;
     int ret = -1;
 
+    qemuDriverLock(driver);
     vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    qemuDriverUnlock(driver);
+
     if (!vm) {
         char uuidstr[VIR_UUID_STRING_BUFLEN];
 
@@ -1776,6 +1868,8 @@ static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) {
     ret = 0;
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -1784,7 +1878,9 @@ static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) {
     virDomainObjPtr vm;
     int ret = -1;
 
+    qemuDriverLock(driver);
     vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    qemuDriverUnlock(driver);
     if (!vm) {
         char uuidstr[VIR_UUID_STRING_BUFLEN];
 
@@ -1810,6 +1906,8 @@ static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) {
     ret = 0;
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -1819,7 +1917,9 @@ static int qemudDomainGetInfo(virDomainPtr dom,
     virDomainObjPtr vm;
     int ret = -1;
 
+    qemuDriverLock(driver);
     vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    qemuDriverUnlock(driver);
     if (!vm) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                          "%s", _("no domain with matching uuid"));
@@ -1843,6 +1943,8 @@ static int qemudDomainGetInfo(virDomainPtr dom,
     ret = 0;
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -1956,6 +2058,7 @@ static int qemudDomainSave(virDomainPtr dom,
     memcpy(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic));
     header.version = QEMUD_SAVE_VERSION;
 
+    qemuDriverLock(driver);
     vm = virDomainFindByID(&driver->domains, dom->id);
 
     if (!vm) {
@@ -1999,7 +2102,7 @@ static int qemudDomainSave(virDomainPtr dom,
     if (safewrite(fd, &header, sizeof(header)) != sizeof(header)) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("failed to write save header"));
-        return -1;
+        goto cleanup;
     }
 
     if (safewrite(fd, xml, header.xml_len) != header.xml_len) {
@@ -2054,9 +2157,11 @@ static int qemudDomainSave(virDomainPtr dom,
     qemudDomainEventDispatch(driver, vm,
                              VIR_DOMAIN_EVENT_STOPPED,
                              VIR_DOMAIN_EVENT_STOPPED_SAVED);
-    if (!vm->persistent)
+    if (!vm->persistent) {
         virDomainRemoveInactive(&driver->domains,
                                 vm);
+        vm = NULL;
+    }
     ret = 0;
 
 cleanup:
@@ -2068,7 +2173,9 @@ cleanup:
     VIR_FREE(info);
     if (ret != 0)
         unlink(path);
-
+    if (vm)
+        virDomainObjUnlock(vm);
+    qemuDriverUnlock(driver);
     return ret;
 }
 
@@ -2079,7 +2186,10 @@ static int qemudDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) {
     int max;
     int ret = -1;
 
+    qemuDriverLock(driver);
     vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    qemuDriverUnlock(driver);
+
     if (!vm) {
         char uuidstr[VIR_UUID_STRING_BUFLEN];
 
@@ -2112,6 +2222,8 @@ static int qemudDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) {
     ret = 0;
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -2129,7 +2241,10 @@ qemudDomainPinVcpu(virDomainPtr dom,
     virNodeInfo nodeinfo;
     int ret = -1;
 
+    qemuDriverLock(driver);
     vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    qemuDriverUnlock(driver);
+
     if (!virDomainIsActive(vm)) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
                          "%s",_("cannot pin vcpus on an inactive domain"));
@@ -2170,6 +2285,8 @@ qemudDomainPinVcpu(virDomainPtr dom,
     ret = 0;
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -2185,7 +2302,10 @@ qemudDomainGetVcpus(virDomainPtr dom,
     int i, v, maxcpu;
     int ret = -1;
 
+    qemuDriverLock(driver);
     vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    qemuDriverUnlock(driver);
+
     if (!virDomainIsActive(vm)) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
                          "%s",_("cannot pin vcpus on an inactive domain"));
@@ -2241,6 +2361,8 @@ qemudDomainGetVcpus(virDomainPtr dom,
     ret = maxinfo;
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 #endif /* HAVE_SCHED_GETAFFINITY */
@@ -2252,7 +2374,10 @@ static int qemudDomainGetMaxVcpus(virDomainPtr dom) {
     const char *type;
     int ret = -1;
 
+    qemuDriverLock(driver);
     vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    qemuDriverUnlock(driver);
+
     if (!vm) {
         char uuidstr[VIR_UUID_STRING_BUFLEN];
 
@@ -2272,6 +2397,8 @@ static int qemudDomainGetMaxVcpus(virDomainPtr dom) {
     ret = qemudGetMaxVCPUs(dom->conn, type);
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -2280,12 +2407,13 @@ static int qemudDomainRestore(virConnectPtr conn,
                               const char *path) {
     struct qemud_driver *driver = conn->privateData;
     virDomainDefPtr def = NULL;
-    virDomainObjPtr vm;
+    virDomainObjPtr vm = NULL;
     int fd = -1;
     int ret = -1;
     char *xml = NULL;
     struct qemud_save_header header;
 
+    qemuDriverLock(driver);
     /* Verify the header and read the XML */
     if ((fd = open(path, O_RDONLY)) < 0) {
         qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
@@ -2359,9 +2487,11 @@ static int qemudDomainRestore(virConnectPtr conn,
     if (ret < 0) {
         qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
                          "%s", _("failed to start VM"));
-        if (!vm->persistent)
+        if (!vm->persistent) {
             virDomainRemoveInactive(&driver->domains,
                                     vm);
+            vm = NULL;
+        }
         goto cleanup;
     }
 
@@ -2387,7 +2517,9 @@ cleanup:
     VIR_FREE(xml);
     if (fd != -1)
         close(fd);
-
+    if (vm)
+        virDomainObjUnlock(vm);
+    qemuDriverUnlock(driver);
     return ret;
 }
 
@@ -2398,7 +2530,10 @@ static char *qemudDomainDumpXML(virDomainPtr dom,
     virDomainObjPtr vm;
     char *ret = NULL;
 
+    qemuDriverLock(driver);
     vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    qemuDriverUnlock(driver);
+
     if (!vm) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                          "%s", _("no domain with matching uuid"));
@@ -2411,6 +2546,8 @@ static char *qemudDomainDumpXML(virDomainPtr dom,
                              flags);
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -2420,21 +2557,27 @@ static int qemudListDefinedDomains(virConnectPtr conn,
     struct qemud_driver *driver = conn->privateData;
     int got = 0, i;
 
+    qemuDriverLock(driver);
     for (i = 0 ; i < driver->domains.count && got < nnames ; i++) {
+        virDomainObjLock(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"));
+                virDomainObjUnlock(driver->domains.objs[i]);
                 goto cleanup;
             }
         }
+        virDomainObjUnlock(driver->domains.objs[i]);
     }
 
+    qemuDriverUnlock(driver);
     return got;
 
  cleanup:
     for (i = 0 ; i < got ; i++)
         VIR_FREE(names[i]);
+    qemuDriverUnlock(driver);
     return -1;
 }
 
@@ -2442,9 +2585,11 @@ static int qemudNumDefinedDomains(virConnectPtr conn) {
     struct qemud_driver *driver = conn->privateData;
     int n = 0, i;
 
+    qemuDriverLock(driver);
     for (i = 0 ; i < driver->domains.count ; i++)
         if (!virDomainIsActive(driver->domains.objs[i]))
             n++;
+    qemuDriverUnlock(driver);
 
     return n;
 }
@@ -2455,7 +2600,10 @@ static int qemudDomainStart(virDomainPtr dom) {
     virDomainObjPtr vm;
     int ret = -1;
 
+    qemuDriverLock(driver);
     vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    qemuDriverUnlock(driver);
+
     if (!vm) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                          "%s", _("no domain with matching uuid"));
@@ -2469,6 +2617,8 @@ static int qemudDomainStart(virDomainPtr dom) {
                                  VIR_DOMAIN_EVENT_STARTED_BOOTED);
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -2476,16 +2626,19 @@ cleanup:
 static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
     struct qemud_driver *driver = conn->privateData;
     virDomainDefPtr def;
-    virDomainObjPtr vm;
+    virDomainObjPtr vm = NULL;
     virDomainPtr dom = NULL;
     int newVM = 1;
 
+    qemuDriverLock(driver);
     if (!(def = virDomainDefParseString(conn, driver->caps, xml)))
         goto cleanup;
 
     vm = virDomainFindByName(&driver->domains, def->name);
-    if (vm)
+    if (vm) {
+        virDomainObjUnlock(vm);
         newVM = 0;
+    }
 
     if (!(vm = virDomainAssignDef(conn,
                                   &driver->domains,
@@ -2500,6 +2653,7 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
                             vm->newDef ? vm->newDef : vm->def) < 0) {
         virDomainRemoveInactive(&driver->domains,
                                 vm);
+        vm = NULL;
         goto cleanup;
     }
 
@@ -2513,6 +2667,9 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
     if (dom) dom->id = vm->def->id;
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    qemuDriverUnlock(driver);
     return dom;
 }
 
@@ -2521,7 +2678,9 @@ static int qemudDomainUndefine(virDomainPtr dom) {
     virDomainObjPtr vm;
     int ret = -1;
 
+    qemuDriverLock(driver);
     vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+
     if (!vm) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                          "%s", _("no domain with matching uuid"));
@@ -2549,9 +2708,13 @@ static int qemudDomainUndefine(virDomainPtr dom) {
 
     virDomainRemoveInactive(&driver->domains,
                             vm);
+    vm = NULL;
     ret = 0;
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    qemuDriverUnlock(driver);
     return ret;
 }
 
@@ -2913,6 +3076,7 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
     virDomainDeviceDefPtr dev = NULL;
     int ret = -1;
 
+    qemuDriverLock(driver);
     vm = virDomainFindByUUID(&driver->domains, dom->uuid);
     if (!vm) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
@@ -2964,6 +3128,9 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
 
 cleanup:
     virDomainDeviceDefFree(dev);
+    if (vm)
+        virDomainObjUnlock(vm);
+    qemuDriverUnlock(driver);
     return ret;
 }
 
@@ -3045,6 +3212,7 @@ static int qemudDomainDetachDevice(virDomainPtr dom,
     virDomainDeviceDefPtr dev = NULL;
     int ret = -1;
 
+    qemuDriverLock(driver);
     vm = virDomainFindByUUID(&driver->domains, dom->uuid);
     if (!vm) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
@@ -3074,16 +3242,22 @@ static int qemudDomainDetachDevice(virDomainPtr dom,
 
 cleanup:
     virDomainDeviceDefFree(dev);
+    if (vm)
+        virDomainObjUnlock(vm);
+    qemuDriverUnlock(driver);
     return ret;
 }
 
 static int qemudDomainGetAutostart(virDomainPtr dom,
-                            int *autostart) {
+                                   int *autostart) {
     struct qemud_driver *driver = dom->conn->privateData;
     virDomainObjPtr vm;
     int ret = -1;
 
+    qemuDriverLock(driver);
     vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    qemuDriverUnlock(driver);
+
     if (!vm) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                          "%s", _("no domain with matching uuid"));
@@ -3094,6 +3268,8 @@ static int qemudDomainGetAutostart(virDomainPtr dom,
     ret = 0;
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -3104,7 +3280,10 @@ static int qemudDomainSetAutostart(virDomainPtr dom,
     char *configFile = NULL, *autostartLink = NULL;
     int ret = -1;
 
+    qemuDriverLock(driver);
     vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    qemuDriverUnlock(driver);
+
     if (!vm) {
         qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                          "%s", _("no domain with matching uuid"));
@@ -3157,7 +3336,8 @@ static int qemudDomainSetAutostart(virDomainPtr dom,
 cleanup:
     VIR_FREE(configFile);
     VIR_FREE(autostartLink);
-
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -3179,7 +3359,9 @@ qemudDomainBlockStats (virDomainPtr dom,
     virDomainObjPtr vm;
     virDomainDiskDefPtr disk = NULL;
 
+    qemuDriverLock(driver);
     vm = virDomainFindByID(&driver->domains, dom->id);
+    qemuDriverUnlock(driver);
     if (!vm) {
         qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                           _("no domain with matching id %d"), dom->id);
@@ -3292,6 +3474,8 @@ qemudDomainBlockStats (virDomainPtr dom,
  cleanup:
     VIR_FREE(qemu_dev_name);
     VIR_FREE(info);
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -3306,7 +3490,10 @@ qemudDomainInterfaceStats (virDomainPtr dom,
     int i;
     int ret = -1;
 
+    qemuDriverLock(driver);
     vm = virDomainFindByID(&driver->domains, dom->id);
+    qemuDriverUnlock(driver);
+
     if (!vm) {
         qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                           _("no domain with matching id %d"), dom->id);
@@ -3341,6 +3528,8 @@ qemudDomainInterfaceStats (virDomainPtr dom,
                           _("invalid path, '%s' is not a known interface"), path);
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 #else
@@ -3365,7 +3554,10 @@ qemudDomainBlockPeek (virDomainPtr dom,
     virDomainObjPtr vm;
     int fd = -1, ret = -1, i;
 
+    qemuDriverLock(driver);
     vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    qemuDriverUnlock(driver);
+
     if (!vm) {
         qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
                           "%s", _("no domain with matching uuid"));
@@ -3417,6 +3609,8 @@ qemudDomainBlockPeek (virDomainPtr dom,
 cleanup:
     if (fd >= 0)
         close (fd);
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -3432,7 +3626,9 @@ qemudDomainMemoryPeek (virDomainPtr dom,
     char tmp[] = TEMPDIR "/qemu.mem.XXXXXX";
     int fd = -1, ret = -1;
 
+    qemuDriverLock(driver);
     vm = virDomainFindByID(&driver->domains, dom->id);
+    qemuDriverUnlock(driver);
 
     if (!vm) {
         qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
@@ -3482,6 +3678,8 @@ cleanup:
     VIR_FREE(info);
     if (fd >= 0) close (fd);
     unlink (tmp);
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -3495,8 +3693,10 @@ qemudDomainEventRegister (virConnectPtr conn,
     struct qemud_driver *driver = conn->privateData;
     int ret;
 
+    qemuDriverLock(driver);
     ret = virDomainEventCallbackListAdd(conn, driver->domainEventCallbacks,
                                         callback, opaque, freecb);
+    qemuDriverUnlock(driver);
 
     return ret;
 }
@@ -3508,8 +3708,10 @@ qemudDomainEventDeregister (virConnectPtr conn,
     struct qemud_driver *driver = conn->privateData;
     int ret;
 
+    qemuDriverLock(driver);
     ret = virDomainEventCallbackListRemove(conn, driver->domainEventCallbacks,
                                            callback);
+    qemuDriverUnlock(driver);
 
     return ret;
 }
@@ -3573,6 +3775,7 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn,
 
     *uri_out = NULL;
 
+    qemuDriverLock(driver);
     if (!dom_xml) {
         qemudReportError (dconn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                           "%s", _("no domain XML passed"));
@@ -3683,9 +3886,10 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn,
     if (qemudStartVMDaemon (dconn, driver, vm, migrateFrom) < 0) {
         qemudReportError (dconn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
                           "%s", _("failed to start listening VM"));
-        if (!vm->persistent)
+        if (!vm->persistent) {
             virDomainRemoveInactive(&driver->domains, vm);
-
+            vm = NULL;
+        }
         goto cleanup;
     }
     qemudDomainEventDispatch(driver, vm,
@@ -3698,7 +3902,9 @@ cleanup:
     if (ret != 0) {
         VIR_FREE(*uri_out);
     }
-
+    if (vm)
+        virDomainObjUnlock(vm);
+    qemuDriverUnlock(driver);
     return ret;
 }
 
@@ -3719,6 +3925,7 @@ qemudDomainMigratePerform (virDomainPtr dom,
     char *info = NULL;
     int ret = -1;
 
+    qemuDriverLock(driver);
     vm = virDomainFindByID(&driver->domains, dom->id);
     if (!vm) {
         qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
@@ -3783,12 +3990,17 @@ qemudDomainMigratePerform (virDomainPtr dom,
     qemudDomainEventDispatch(driver, vm,
                              VIR_DOMAIN_EVENT_STOPPED,
                              VIR_DOMAIN_EVENT_STOPPED_MIGRATED);
-    if (!vm->persistent)
+    if (!vm->persistent) {
         virDomainRemoveInactive(&driver->domains, vm);
+        vm = NULL;
+    }
     ret = 0;
 
 cleanup:
     VIR_FREE(info);
+    if (vm)
+        virDomainObjUnlock(vm);
+    qemuDriverUnlock(driver);
     return ret;
 }
 
@@ -3807,6 +4019,7 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn,
     virDomainPtr dom = NULL;
     char *info = NULL;
 
+    qemuDriverLock(driver);
     vm = virDomainFindByName(&driver->domains, dname);
     if (!vm) {
         qemudReportError (dconn, NULL, NULL, VIR_ERR_INVALID_DOMAIN,
@@ -3829,11 +4042,16 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn,
         qemudDomainEventDispatch(driver, vm,
                                  VIR_DOMAIN_EVENT_STOPPED,
                                  VIR_DOMAIN_EVENT_STOPPED_FAILED);
-        if (!vm->persistent)
+        if (!vm->persistent) {
             virDomainRemoveInactive(&driver->domains, vm);
+            vm = NULL;
+        }
     }
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    qemuDriverUnlock(driver);
     return dom;
 }