Current processing requires a "fire dance" unlocking the @obj,
adding an @obj ref, locking the @interfaces, and relocking @obj
in order to ensure proper lock ordering.
This can be avoided by changing virInterfaceObjListRemove to
take @name instead of @obj. Then, we can lock the @interfaces
list, look up the @obj by @name (like we do when adding), and
remove the @obj from the list. This removes the last reference
to the object effectively reaping it.
NB: Since prior to calling we remove the reference to the object
we cannot pass anything contained within the object (such as the
obj->def or obj->def->name) because it's possible that the object
could be reaped by two competing remove threads.
Signed-off-by: John Ferlan <jferlan(a)redhat.com>
---
src/conf/virinterfaceobj.c | 26 +++++++++++++++++---------
src/conf/virinterfaceobj.h | 2 +-
src/test/test_driver.c | 4 ++--
3 files changed, 20 insertions(+), 12 deletions(-)
diff --git a/src/conf/virinterfaceobj.c b/src/conf/virinterfaceobj.c
index f90c0bd9c..c3a7d4cd8 100644
--- a/src/conf/virinterfaceobj.c
+++ b/src/conf/virinterfaceobj.c
@@ -358,20 +358,28 @@ virInterfaceObjListAssignDef(virInterfaceObjListPtr interfaces,
}
+/*
+ * virInterfaceObjListRemove:
+ * @interfaces: list of interface objects
+ * @name: name of interface definition to remove
+ *
+ * Find the object by name in the list, remove the object from the
+ * list hash table, and free the object.
+ *
+ * Upon entry it's expected that prior to entry any locks on
+ * the object related to @name will have been removed.
+ */
void
virInterfaceObjListRemove(virInterfaceObjListPtr interfaces,
- virInterfaceObjPtr obj)
+ const char *name)
{
- if (!obj)
- return;
+ virInterfaceObjPtr obj;
- virObjectRef(obj);
- virObjectUnlock(obj);
virObjectRWLockWrite(interfaces);
- virObjectLock(obj);
- virHashRemoveEntry(interfaces->objsName, obj->def->name);
- virObjectUnlock(obj);
- virObjectUnref(obj);
+ if ((obj = virInterfaceObjListFindByNameLocked(interfaces, name))) {
+ virHashRemoveEntry(interfaces->objsName, name);
+ virInterfaceObjEndAPI(&obj);
+ }
virObjectRWUnlock(interfaces);
}
diff --git a/src/conf/virinterfaceobj.h b/src/conf/virinterfaceobj.h
index 799d38038..82eb2ee87 100644
--- a/src/conf/virinterfaceobj.h
+++ b/src/conf/virinterfaceobj.h
@@ -66,7 +66,7 @@ virInterfaceObjListAssignDef(virInterfaceObjListPtr interfaces,
void
virInterfaceObjListRemove(virInterfaceObjListPtr interfaces,
- virInterfaceObjPtr obj);
+ const char *name);
typedef bool
(*virInterfaceObjListFilter)(virConnectPtr conn,
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 99c27cc0a..ddddd8dcb 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -4092,8 +4092,8 @@ testInterfaceUndefine(virInterfacePtr iface)
if (!(obj = testInterfaceObjFindByName(privconn, iface->name)))
return -1;
- virInterfaceObjListRemove(privconn->ifaces, obj);
- virObjectUnref(obj);
+ virInterfaceObjEndAPI(&obj);
+ virInterfaceObjListRemove(privconn->ifaces, iface->name);
return 0;
}
--
2.13.6