[libvirt] PATCH: 7/28: Thread safety for QEMU driver

Daniel P. Berrange berrange at redhat.com
Sun Nov 30 23:33:06 UTC 2008


This patch makes the QEMU driver threadsafe with the exception of the
domain events code.

 qemu_conf.h   |    2 
 qemu_driver.c |  458 ++++++++++++++++++++++++++++++++++++++++++----------------
 2 files changed, 337 insertions(+), 123 deletions(-)


Daniel

diff --git a/src/qemu_conf.h b/src/qemu_conf.h
--- a/src/qemu_conf.h
+++ b/src/qemu_conf.h
@@ -51,6 +51,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,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_drive
 
     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_drive
                                          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,
@@ -229,20 +243,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);
 
-    return 0;
-
- out_of_memory:
+    qemuDriverUnlock(qemu_driver);
+
+    return 0;
+
+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 +283,7 @@ qemudReload(void) {
     if (!qemu_driver)
         return 0;
 
+    qemuDriverLock(qemu_driver);
     virDomainLoadAllConfigs(NULL,
                             qemu_driver->caps,
                             &qemu_driver->domains,
@@ -275,6 +292,7 @@ qemudReload(void) {
                             qemudNotifyLoadDomain, qemu_driver);
 
     qemudAutostartConfigs(qemu_driver);
+    qemuDriverUnlock(qemu_driver);
 
     return 0;
 }
@@ -290,16 +308,18 @@ static int
 static int
 qemudActive(void) {
     unsigned int i;
+    int active = 0;
 
     if (!qemu_driver)
         return 0;
 
+    qemuDriverLock(qemu_driver);
     for (i = 0 ; i < qemu_driver->domains.count ; i++)
         if (virDomainIsActive(qemu_driver->domains.objs[i]))
-            return 1;
-
-    /* Otherwise we're happy to deal with a shutdown */
-    return 0;
+            active = 1;
+
+    qemuDriverUnlock(qemu_driver);
+    return active;
 }
 
 /**
@@ -314,16 +334,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 +360,7 @@ qemudShutdown(void) {
     if (qemu_driver->brctl)
         brShutdown(qemu_driver->brctl);
 
+    qemuDriverUnlock(qemu_driver);
     VIR_FREE(qemu_driver);
 
     return 0;
@@ -1047,38 +1068,15 @@ static void qemudShutdownVMDaemon(virCon
     }
 }
 
-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 ||
@@ -1089,18 +1087,38 @@ qemudDispatchVMEvent(int watch, int fd, 
     }
 
     if (!vm)
-        return;
+        goto cleanup;
 
     if (vm->stdout_fd != fd &&
         vm->stderr_fd != fd) {
-        qemudDispatchVMFailure(driver, vm, fd);
-        return;
-    }
-
-    if (events == VIR_EVENT_HANDLE_READABLE)
-        qemudDispatchVMLog(driver, vm, fd);
-    else
-        qemudDispatchVMFailure(driver, vm, fd);
+        failed = 1;
+    } else {
+        if (events & VIR_EVENT_HANDLE_READABLE) {
+            if (qemudVMData(driver, vm, fd) < 0)
+                failed = 1;
+        } else {
+            quit = 1;
+        }
+    }
+
+    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 +1329,11 @@ static char *qemudGetCapabilities(virCon
     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 +1443,9 @@ static virDomainPtr qemudDomainLookupByI
     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 +1456,21 @@ static virDomainPtr qemudDomainLookupByI
     if (dom) dom->id = vm->def->id;
 
 cleanup:
-    return dom;
-}
+    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 +1480,21 @@ static virDomainPtr qemudDomainLookupByU
     if (dom) dom->id = vm->def->id;
 
 cleanup:
-    return dom;
-}
+    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 +1504,8 @@ static virDomainPtr qemudDomainLookupByN
     if (dom) dom->id = vm->def->id;
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return dom;
 }
 
@@ -1477,6 +1513,7 @@ static int qemudGetVersion(virConnectPtr
     struct qemud_driver *driver = conn->privateData;
     int ret = -1;
 
+    qemuDriverLock(driver);
     if (qemudExtractVersion(conn, driver) < 0)
         goto cleanup;
 
@@ -1484,6 +1521,7 @@ static int qemudGetVersion(virConnectPtr
     ret = 0;
 
 cleanup:
+    qemuDriverUnlock(driver);
     return ret;
 }
 
@@ -1513,29 +1551,42 @@ static int qemudListDomains(virConnectPt
     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;
-    virDomainPtr dom = NULL;
-
+    virDomainObjPtr vm = NULL;
+    virDomainPtr dom = NULL;
+
+    qemuDriverLock(driver);
     if (!(def = virDomainDefParseString(conn, driver->caps, xml)))
         goto cleanup;
 
@@ -1567,6 +1618,7 @@ static virDomainPtr qemudDomainCreate(vi
     if (qemudStartVMDaemon(conn, driver, vm, NULL) < 0) {
         virDomainRemoveInactive(&driver->domains,
                                 vm);
+        vm = NULL;
         goto cleanup;
     }
     qemudDomainEventDispatch(driver, vm,
@@ -1578,7 +1630,9 @@ static virDomainPtr qemudDomainCreate(vi
 
 cleanup:
     virDomainDefFree(def);
-
+    if (vm)
+        virDomainObjUnlock(vm);
+    qemuDriverUnlock(driver);
     return dom;
 }
 
@@ -1589,7 +1643,10 @@ static int qemudDomainSuspend(virDomainP
     virDomainObjPtr vm;
     int ret = -1;
 
-    vm = virDomainFindByID(&driver->domains, dom->id);
+    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 +1672,8 @@ static int qemudDomainSuspend(virDomainP
     ret = 0;
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -1625,7 +1684,10 @@ static int qemudDomainResume(virDomainPt
     virDomainObjPtr vm;
     int ret = -1;
 
-    vm = virDomainFindByID(&driver->domains, dom->id);
+    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 +1714,8 @@ static int qemudDomainResume(virDomainPt
     ret = 0;
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -1662,7 +1726,10 @@ static int qemudDomainShutdown(virDomain
     char* info;
     int ret = -1;
 
-    vm = virDomainFindByID(&driver->domains, dom->id);
+    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 +1745,9 @@ static int qemudDomainShutdown(virDomain
     ret = 0;
 
 cleanup:
-    return ret;
-
+    if (vm)
+        virDomainObjUnlock(vm);
+    return ret;
 }
 
 
@@ -1688,6 +1756,7 @@ static int qemudDomainDestroy(virDomainP
     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 +1768,17 @@ static int qemudDomainDestroy(virDomainP
     qemudDomainEventDispatch(driver, vm,
                              VIR_DOMAIN_EVENT_STOPPED,
                              VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
-    if (!vm->persistent)
+    if (!vm->persistent) {
         virDomainRemoveInactive(&driver->domains,
                                 vm);
-    ret = 0;
-
-cleanup:
+        vm = NULL;
+    }
+    ret = 0;
+
+cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    qemuDriverUnlock(driver);
     return ret;
 }
 
@@ -1714,7 +1788,9 @@ static char *qemudDomainGetOSType(virDom
     virDomainObjPtr vm;
     char *type = NULL;
 
-    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    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 +1802,8 @@ static char *qemudDomainGetOSType(virDom
                          "%s", _("failed to allocate space for ostype"));
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return type;
 }
 
@@ -1735,7 +1813,10 @@ static unsigned long qemudDomainGetMaxMe
     virDomainObjPtr vm;
     unsigned long ret = 0;
 
-    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    qemuDriverLock(driver);
+    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    qemuDriverUnlock(driver);
+
     if (!vm) {
         char uuidstr[VIR_UUID_STRING_BUFLEN];
 
@@ -1748,6 +1829,8 @@ static unsigned long qemudDomainGetMaxMe
     ret = vm->def->maxmem;
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -1756,7 +1839,10 @@ static int qemudDomainSetMaxMemory(virDo
     virDomainObjPtr vm;
     int ret = -1;
 
-    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    qemuDriverLock(driver);
+    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    qemuDriverUnlock(driver);
+
     if (!vm) {
         char uuidstr[VIR_UUID_STRING_BUFLEN];
 
@@ -1776,6 +1862,8 @@ static int qemudDomainSetMaxMemory(virDo
     ret = 0;
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -1784,7 +1872,9 @@ static int qemudDomainSetMemory(virDomai
     virDomainObjPtr vm;
     int ret = -1;
 
-    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    qemuDriverLock(driver);
+    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    qemuDriverUnlock(driver);
     if (!vm) {
         char uuidstr[VIR_UUID_STRING_BUFLEN];
 
@@ -1810,6 +1900,8 @@ static int qemudDomainSetMemory(virDomai
     ret = 0;
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -1819,7 +1911,9 @@ static int qemudDomainGetInfo(virDomainP
     virDomainObjPtr vm;
     int ret = -1;
 
-    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    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 +1937,8 @@ static int qemudDomainGetInfo(virDomainP
     ret = 0;
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -1956,6 +2052,7 @@ static int qemudDomainSave(virDomainPtr 
     memcpy(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic));
     header.version = QEMUD_SAVE_VERSION;
 
+    qemuDriverLock(driver);
     vm = virDomainFindByID(&driver->domains, dom->id);
 
     if (!vm) {
@@ -2054,9 +2151,11 @@ static int qemudDomainSave(virDomainPtr 
     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 +2167,9 @@ cleanup:
     VIR_FREE(info);
     if (ret != 0)
         unlink(path);
-
+    if (vm)
+        virDomainObjUnlock(vm);
+    qemuDriverUnlock(driver);
     return ret;
 }
 
@@ -2079,7 +2180,10 @@ static int qemudDomainSetVcpus(virDomain
     int max;
     int ret = -1;
 
-    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    qemuDriverLock(driver);
+    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    qemuDriverUnlock(driver);
+
     if (!vm) {
         char uuidstr[VIR_UUID_STRING_BUFLEN];
 
@@ -2112,6 +2216,8 @@ static int qemudDomainSetVcpus(virDomain
     ret = 0;
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -2129,7 +2235,10 @@ qemudDomainPinVcpu(virDomainPtr dom,
     virNodeInfo nodeinfo;
     int ret = -1;
 
-    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    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 +2279,8 @@ qemudDomainPinVcpu(virDomainPtr dom,
     ret = 0;
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -2185,7 +2296,10 @@ qemudDomainGetVcpus(virDomainPtr dom,
     int i, v, maxcpu;
     int ret = -1;
 
-    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    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 +2355,8 @@ qemudDomainGetVcpus(virDomainPtr dom,
     ret = maxinfo;
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 #endif /* HAVE_SCHED_GETAFFINITY */
@@ -2252,7 +2368,10 @@ static int qemudDomainGetMaxVcpus(virDom
     const char *type;
     int ret = -1;
 
-    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    qemuDriverLock(driver);
+    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    qemuDriverUnlock(driver);
+
     if (!vm) {
         char uuidstr[VIR_UUID_STRING_BUFLEN];
 
@@ -2272,6 +2391,8 @@ static int qemudDomainGetMaxVcpus(virDom
     ret = qemudGetMaxVCPUs(dom->conn, type);
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -2280,12 +2401,13 @@ static int qemudDomainRestore(virConnect
                               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 +2481,11 @@ static int qemudDomainRestore(virConnect
     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 +2511,9 @@ cleanup:
     VIR_FREE(xml);
     if (fd != -1)
         close(fd);
-
+    if (vm)
+        virDomainObjUnlock(vm);
+    qemuDriverUnlock(driver);
     return ret;
 }
 
@@ -2398,7 +2524,10 @@ static char *qemudDomainDumpXML(virDomai
     virDomainObjPtr vm;
     char *ret = NULL;
 
-    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    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 +2540,8 @@ static char *qemudDomainDumpXML(virDomai
                              flags);
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -2420,21 +2551,27 @@ static int qemudListDefinedDomains(virCo
     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"));
-                goto cleanup;
-            }
-        }
-    }
-
+                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 +2579,11 @@ static int qemudNumDefinedDomains(virCon
     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 +2594,10 @@ static int qemudDomainStart(virDomainPtr
     virDomainObjPtr vm;
     int ret = -1;
 
-    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    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 +2611,8 @@ static int qemudDomainStart(virDomainPtr
                                  VIR_DOMAIN_EVENT_STARTED_BOOTED);
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -2476,16 +2620,19 @@ static virDomainPtr qemudDomainDefine(vi
 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 +2647,7 @@ static virDomainPtr qemudDomainDefine(vi
                             vm->newDef ? vm->newDef : vm->def) < 0) {
         virDomainRemoveInactive(&driver->domains,
                                 vm);
+        vm = NULL;
         goto cleanup;
     }
 
@@ -2513,6 +2661,9 @@ static virDomainPtr qemudDomainDefine(vi
     if (dom) dom->id = vm->def->id;
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    qemuDriverUnlock(driver);
     return dom;
 }
 
@@ -2521,7 +2672,9 @@ static int qemudDomainUndefine(virDomain
     virDomainObjPtr vm;
     int ret = -1;
 
-    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    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 +2702,13 @@ static int qemudDomainUndefine(virDomain
 
     virDomainRemoveInactive(&driver->domains,
                             vm);
-    ret = 0;
-
-cleanup:
+    vm = NULL;
+    ret = 0;
+
+cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    qemuDriverUnlock(driver);
     return ret;
 }
 
@@ -2913,6 +3070,7 @@ static int qemudDomainAttachDevice(virDo
     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 +3122,9 @@ static int qemudDomainAttachDevice(virDo
 
 cleanup:
     virDomainDeviceDefFree(dev);
+    if (vm)
+        virDomainObjUnlock(vm);
+    qemuDriverUnlock(driver);
     return ret;
 }
 
@@ -3045,6 +3206,7 @@ static int qemudDomainDetachDevice(virDo
     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 +3236,22 @@ static int qemudDomainDetachDevice(virDo
 
 cleanup:
     virDomainDeviceDefFree(dev);
+    if (vm)
+        virDomainObjUnlock(vm);
+    qemuDriverUnlock(driver);
     return ret;
 }
 
 static int qemudDomainGetAutostart(virDomainPtr dom,
-                            int *autostart) {
-    struct qemud_driver *driver = dom->conn->privateData;
-    virDomainObjPtr vm;
-    int ret = -1;
-
-    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+                                   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 +3262,8 @@ static int qemudDomainGetAutostart(virDo
     ret = 0;
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -3104,7 +3274,10 @@ static int qemudDomainSetAutostart(virDo
     char *configFile = NULL, *autostartLink = NULL;
     int ret = -1;
 
-    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    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 +3330,8 @@ cleanup:
 cleanup:
     VIR_FREE(configFile);
     VIR_FREE(autostartLink);
-
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -3179,7 +3353,9 @@ qemudDomainBlockStats (virDomainPtr dom,
     virDomainObjPtr vm;
     virDomainDiskDefPtr disk = NULL;
 
-    vm = virDomainFindByID(&driver->domains, dom->id);
+    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 +3468,8 @@ qemudDomainBlockStats (virDomainPtr dom,
  cleanup:
     VIR_FREE(qemu_dev_name);
     VIR_FREE(info);
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -3306,7 +3484,10 @@ qemudDomainInterfaceStats (virDomainPtr 
     int i;
     int ret = -1;
 
-    vm = virDomainFindByID(&driver->domains, dom->id);
+    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 +3522,8 @@ qemudDomainInterfaceStats (virDomainPtr 
                           _("invalid path, '%s' is not a known interface"), path);
 
 cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 #else
@@ -3365,7 +3548,10 @@ qemudDomainBlockPeek (virDomainPtr dom,
     virDomainObjPtr vm;
     int fd = -1, ret = -1, i;
 
-    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    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 +3603,8 @@ cleanup:
 cleanup:
     if (fd >= 0)
         close (fd);
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -3432,7 +3620,9 @@ qemudDomainMemoryPeek (virDomainPtr dom,
     char tmp[] = TEMPDIR "/qemu.mem.XXXXXX";
     int fd = -1, ret = -1;
 
-    vm = virDomainFindByID(&driver->domains, dom->id);
+    qemuDriverLock(driver);
+    vm = virDomainFindByID(&driver->domains, dom->id);
+    qemuDriverUnlock(driver);
 
     if (!vm) {
         qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
@@ -3482,6 +3672,8 @@ cleanup:
     VIR_FREE(info);
     if (fd >= 0) close (fd);
     unlink (tmp);
+    if (vm)
+        virDomainObjUnlock(vm);
     return ret;
 }
 
@@ -3495,8 +3687,10 @@ qemudDomainEventRegister (virConnectPtr 
     struct qemud_driver *driver = conn->privateData;
     int ret;
 
+    qemuDriverLock(driver);
     ret = virDomainEventCallbackListAdd(conn, driver->domainEventCallbacks,
                                         callback, opaque, freecb);
+    qemuDriverUnlock(driver);
 
     return ret;
 }
@@ -3508,8 +3702,10 @@ qemudDomainEventDeregister (virConnectPt
     struct qemud_driver *driver = conn->privateData;
     int ret;
 
+    qemuDriverLock(driver);
     ret = virDomainEventCallbackListRemove(conn, driver->domainEventCallbacks,
                                            callback);
+    qemuDriverUnlock(driver);
 
     return ret;
 }
@@ -3573,6 +3769,7 @@ qemudDomainMigratePrepare2 (virConnectPt
 
     *uri_out = NULL;
 
+    qemuDriverLock(driver);
     if (!dom_xml) {
         qemudReportError (dconn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                           "%s", _("no domain XML passed"));
@@ -3683,9 +3880,10 @@ qemudDomainMigratePrepare2 (virConnectPt
     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 +3896,9 @@ cleanup:
     if (ret != 0) {
         VIR_FREE(*uri_out);
     }
-
+    if (vm)
+        virDomainObjUnlock(vm);
+    qemuDriverUnlock(driver);
     return ret;
 }
 
@@ -3719,6 +3919,7 @@ qemudDomainMigratePerform (virDomainPtr 
     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 +3984,17 @@ qemudDomainMigratePerform (virDomainPtr 
     qemudDomainEventDispatch(driver, vm,
                              VIR_DOMAIN_EVENT_STOPPED,
                              VIR_DOMAIN_EVENT_STOPPED_MIGRATED);
-    if (!vm->persistent)
+    if (!vm->persistent) {
         virDomainRemoveInactive(&driver->domains, vm);
-    ret = 0;
-
-cleanup:
-    VIR_FREE(info);
+        vm = NULL;
+    }
+    ret = 0;
+
+cleanup:
+    VIR_FREE(info);
+    if (vm)
+        virDomainObjUnlock(vm);
+    qemuDriverUnlock(driver);
     return ret;
 }
 
@@ -3807,6 +4013,7 @@ qemudDomainMigrateFinish2 (virConnectPtr
     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 +4036,16 @@ qemudDomainMigrateFinish2 (virConnectPtr
         qemudDomainEventDispatch(driver, vm,
                                  VIR_DOMAIN_EVENT_STOPPED,
                                  VIR_DOMAIN_EVENT_STOPPED_FAILED);
-        if (!vm->persistent)
+        if (!vm->persistent) {
             virDomainRemoveInactive(&driver->domains, vm);
-    }
-
-cleanup:
+            vm = NULL;
+        }
+    }
+
+cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    qemuDriverUnlock(driver);
     return dom;
 }
 

-- 
|: 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 :|




More information about the libvir-list mailing list