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 a9c8573..79bb274 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 8599ee7..675a49b 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 600dfee..52f1a05 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