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 -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list