[libvirt] [PATCH 17/21] Add reference counting on virDomainObjPtr objects

Daniel P. Berrange berrange at redhat.com
Fri Oct 23 13:05:46 UTC 2009


Add reference counting on the virDomainObjPtr objects. With the
forthcoming asynchronous QEMU monitor, it will be neccessary to
release the lock on virDomainObjPtr while waiting for a monitor
command response. It is neccessary to ensure one thread can't
delete a virDomainObjPtr while another is waiting. By introducing
reference counting threads can make sure objects they are using
are not accidentally deleted while unlocked.

* src/conf/domain_conf.h, src/conf/domain_conf.c: Add
  virDomainObjRef/Unref APIs, remove virDomainObjFree
* src/openvz/openvz_conf.c: replace call to virDomainObjFree
  with virDomainObjUnref
---
 src/conf/domain_conf.c   |   32 ++++++++++++++++++++++++++++----
 src/conf/domain_conf.h   |    5 ++++-
 src/libvirt_private.syms |    3 ++-
 src/openvz/openvz_conf.c |    6 +++++-
 4 files changed, 39 insertions(+), 7 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index a6d8e07..82bec2a 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -219,7 +219,9 @@ int virDomainObjListInit(virDomainObjListPtr doms)
 static void virDomainObjListDeallocator(void *payload, const char *name ATTRIBUTE_UNUSED)
 {
     virDomainObjPtr obj = payload;
-    virDomainObjFree(obj);
+    virDomainObjLock(obj);
+    if (!virDomainObjUnref(obj))
+        virDomainObjUnlock(obj);
 }
 
 void virDomainObjListDeinit(virDomainObjListPtr doms)
@@ -582,11 +584,12 @@ void virDomainDefFree(virDomainDefPtr def)
 
 #ifndef PROXY
 
-void virDomainObjFree(virDomainObjPtr dom)
+static void virDomainObjFree(virDomainObjPtr dom)
 {
     if (!dom)
         return;
 
+    VIR_DEBUG("obj=%p", dom);
     virDomainDefFree(dom->def);
     virDomainDefFree(dom->newDef);
 
@@ -602,6 +605,25 @@ void virDomainObjFree(virDomainObjPtr dom)
     VIR_FREE(dom);
 }
 
+void virDomainObjRef(virDomainObjPtr dom)
+{
+    dom->refs++;
+    VIR_DEBUG("obj=%p refs=%d", dom, dom->refs);
+}
+
+
+int virDomainObjUnref(virDomainObjPtr dom)
+{
+    dom->refs--;
+    VIR_DEBUG("obj=%p refs=%d", dom, dom->refs);
+    if (dom->refs == 0) {
+        virDomainObjUnlock(dom);
+        virDomainObjFree(dom);
+        return 1;
+    }
+    return 0;
+}
+
 static virDomainObjPtr virDomainObjNew(virConnectPtr conn,
                                        virCapsPtr caps)
 {
@@ -633,7 +655,9 @@ static virDomainObjPtr virDomainObjNew(virConnectPtr conn,
     domain->state = VIR_DOMAIN_SHUTOFF;
     domain->monitorWatch = -1;
     domain->monitor = -1;
+    domain->refs = 1;
 
+    VIR_DEBUG("obj=%p", domain);
     return domain;
 }
 
@@ -3305,7 +3329,7 @@ static virDomainObjPtr virDomainObjParseXML(virConnectPtr conn,
 error:
     VIR_FREE(nodes);
     virDomainChrDefFree(obj->monitor_chr);
-    virDomainObjFree(obj);
+    virDomainObjUnref(obj);
     return NULL;
 }
 
@@ -4846,7 +4870,7 @@ static virDomainObjPtr virDomainLoadStatus(virConnectPtr conn,
     return obj;
 
 error:
-    virDomainObjFree(obj);
+    virDomainObjUnref(obj);
     VIR_FREE(statusFile);
     return NULL;
 }
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 8a8bfb0..5202034 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -621,6 +621,7 @@ typedef struct _virDomainObj virDomainObj;
 typedef virDomainObj *virDomainObjPtr;
 struct _virDomainObj {
     virMutex lock;
+    int refs;
 
     int monitor;
     virDomainChrDefPtr monitor_chr;
@@ -678,7 +679,9 @@ void virDomainVideoDefFree(virDomainVideoDefPtr def);
 void virDomainHostdevDefFree(virDomainHostdevDefPtr def);
 void virDomainDeviceDefFree(virDomainDeviceDefPtr def);
 void virDomainDefFree(virDomainDefPtr vm);
-void virDomainObjFree(virDomainObjPtr vm);
+void virDomainObjRef(virDomainObjPtr vm);
+/* Returns 1 if the object was freed, 0 if more refs exist */
+int virDomainObjUnref(virDomainObjPtr vm);
 
 virDomainObjPtr virDomainAssignDef(virConnectPtr conn,
                                    virCapsPtr caps,
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 6ed562d..4f2f048 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -123,7 +123,6 @@ virDomainLifecycleTypeToString;
 virDomainLoadAllConfigs;
 virDomainNetDefFree;
 virDomainNetTypeToString;
-virDomainObjFree;
 virDomainRemoveInactive;
 virDomainSaveXML;
 virDomainSaveConfig;
@@ -151,6 +150,8 @@ virDomainObjListGetActiveIDs;
 virDomainObjListNumOfDomains;
 virDomainObjListInit;
 virDomainObjListDeinit;
+virDomainObjRef;
+virDomainObjUnref;
 
 
 # domain_event.h
diff --git a/src/openvz/openvz_conf.c b/src/openvz/openvz_conf.c
index c928afb..c2a39d0 100644
--- a/src/openvz/openvz_conf.c
+++ b/src/openvz/openvz_conf.c
@@ -463,6 +463,8 @@ int openvzLoadDomains(struct openvz_driver *driver) {
             goto cleanup;
         }
 
+        virDomainObjLock(dom);
+
         if (VIR_ALLOC(dom->def) < 0)
             goto no_memory;
 
@@ -471,6 +473,7 @@ int openvzLoadDomains(struct openvz_driver *driver) {
         else
             dom->state = VIR_DOMAIN_RUNNING;
 
+        dom->refs = 1;
         dom->pid = veid;
         dom->def->id = dom->state == VIR_DOMAIN_SHUTOFF ? -1 : veid;
 
@@ -513,6 +516,7 @@ int openvzLoadDomains(struct openvz_driver *driver) {
         if (virHashAddEntry(driver->domains.objs, uuidstr, dom) < 0)
             goto no_memory;
 
+        virDomainObjUnlock(dom);
         dom = NULL;
     }
 
@@ -525,7 +529,7 @@ int openvzLoadDomains(struct openvz_driver *driver) {
 
  cleanup:
     fclose(fp);
-    virDomainObjFree(dom);
+    virDomainObjUnref(dom);
     return -1;
 }
 
-- 
1.6.2.5




More information about the libvir-list mailing list