From a340f9131aa7ec38f6fe7cede0695f2c7fcf5631 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Thu, 15 Oct 2009 12:30:26 +0100 Subject: [PATCH] Add reference counting on virDomainObjPtr objects 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 28bee54d51..25cb437eff 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -228,7 +228,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) @@ -602,11 +604,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); @@ -622,6 +625,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) { @@ -653,7 +675,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; } @@ -3455,7 +3479,7 @@ static virDomainObjPtr virDomainObjParseXML(virConnectPtr conn, error: VIR_FREE(nodes); virDomainChrDefFree(obj->monitor_chr); - virDomainObjFree(obj); + virDomainObjUnref(obj); return NULL; } @@ -5052,7 +5076,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 fadf43f023..f12c722277 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -640,6 +640,7 @@ typedef struct _virDomainObj virDomainObj; typedef virDomainObj *virDomainObjPtr; struct _virDomainObj { virMutex lock; + int refs; int monitor; virDomainChrDefPtr monitor_chr; @@ -697,7 +698,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 b360e7126f..05068672cb 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -123,7 +123,6 @@ virDomainLifecycleTypeToString; virDomainLoadAllConfigs; virDomainNetDefFree; virDomainNetTypeToString; -virDomainObjFree; virDomainRemoveInactive; virDomainSaveXML; virDomainSaveConfig; @@ -152,6 +151,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 6eeece899f..f4c62f33f3 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; } -- 2.39.5