[libvirt] [PATCH v2 3/9] interface: Alter virInterfaceObjListRemove processing

John Ferlan jferlan at redhat.com
Wed Mar 28 21:19:27 UTC 2018


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 at 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




More information about the libvir-list mailing list