[PATCH v2 9/9] storagepool: Alter virStoragePoolObjRemove processing

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Current processing requires a "fire dance" unlocking the @obj,
adding an @obj ref, locking the @pools, and relocking @obj in
order to ensure proper lock ordering.

This can be avoided by changing virStoragePoolObjRemove to
take a @name instead of @obj. Then, we can lock the @pools
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@xxxxxxxxxx>
---
 src/conf/virstorageobj.c     | 41 +++++++++++++++++++++++++++++------------
 src/conf/virstorageobj.h     |  2 +-
 src/storage/storage_driver.c | 44 +++++++++++++++++++++++++++++---------------
 src/test/test_driver.c       | 30 +++++++++++++++++++-----------
 4 files changed, 78 insertions(+), 39 deletions(-)

diff --git a/src/conf/virstorageobj.c b/src/conf/virstorageobj.c
index f48f08a64..df6febfd0 100644
--- a/src/conf/virstorageobj.c
+++ b/src/conf/virstorageobj.c
@@ -1034,21 +1034,31 @@ virStoragePoolObjVolumeListExport(virConnectPtr conn,
 }
 
 
+/*
+ * virStoragePoolObjRemove:
+ * @pools: list of storage pool objects
+ * @name: name of storage pool to remove
+ *
+ * Find the object by name in the list, remove the object from
+ * each hash table in the list, 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
 virStoragePoolObjRemove(virStoragePoolObjListPtr pools,
-                        virStoragePoolObjPtr obj)
+                        const char *name)
 {
+    virStoragePoolObjPtr obj;
     char uuidstr[VIR_UUID_STRING_BUFLEN];
 
-    virUUIDFormat(obj->def->uuid, uuidstr);
-    virObjectRef(obj);
-    virObjectUnlock(obj);
     virObjectRWLockWrite(pools);
-    virObjectLock(obj);
-    virHashRemoveEntry(pools->objs, uuidstr);
-    virHashRemoveEntry(pools->objsName, obj->def->name);
-    virObjectUnlock(obj);
-    virObjectUnref(obj);
+    if ((obj = virStoragePoolObjFindByNameLocked(pools, name))) {
+        virUUIDFormat(obj->def->uuid, uuidstr);
+        virHashRemoveEntry(pools->objs, uuidstr);
+        virHashRemoveEntry(pools->objsName, name);
+        virStoragePoolObjEndAPI(&obj);
+    }
     virObjectRWUnlock(pools);
 }
 
@@ -1117,6 +1127,7 @@ virStoragePoolObjLoad(virStoragePoolObjListPtr pools,
 {
     virStoragePoolDefPtr def = NULL;
     virStoragePoolObjPtr obj = NULL;
+    char *name = NULL;
 
     if (!(def = virStoragePoolDefParseFile(path)))
         return NULL;
@@ -1129,6 +1140,9 @@ virStoragePoolObjLoad(virStoragePoolObjListPtr pools,
         goto error;
     }
 
+    if (VIR_STRDUP(name, def->name) < 0)
+        goto error;
+
     if (!(obj = virStoragePoolObjAssignDef(pools, def)))
         goto error;
     def = NULL;
@@ -1144,13 +1158,16 @@ virStoragePoolObjLoad(virStoragePoolObjListPtr pools,
     obj->autostart = virFileLinkPointsTo(obj->autostartLink,
                                          obj->configFile);
 
+    VIR_FREE(name);
+
     return obj;
 
  error:
-    if (obj) {
-        virStoragePoolObjRemove(pools, obj);
-        virObjectUnref(obj);
+    if (obj && name) {
+        virStoragePoolObjEndAPI(&obj);
+        virStoragePoolObjRemove(pools, name);
     }
+    VIR_FREE(name);
     virStoragePoolDefFree(def);
     return NULL;
 }
diff --git a/src/conf/virstorageobj.h b/src/conf/virstorageobj.h
index dd7001c4b..047b08a92 100644
--- a/src/conf/virstorageobj.h
+++ b/src/conf/virstorageobj.h
@@ -242,7 +242,7 @@ virStoragePoolObjListNew(void);
 
 void
 virStoragePoolObjRemove(virStoragePoolObjListPtr pools,
-                        virStoragePoolObjPtr obj);
+                        const char *name);
 
 int
 virStoragePoolObjIsDuplicate(virStoragePoolObjListPtr pools,
diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
index 6276545eb..814e5cb97 100644
--- a/src/storage/storage_driver.c
+++ b/src/storage/storage_driver.c
@@ -82,19 +82,21 @@ static void storageDriverUnlock(void)
 /**
  * virStoragePoolUpdateInactive:
  * @poolptr: pointer to a variable holding the pool object pointer
+ * @name: Name of the pool
  *
  * This function is supposed to be called after a pool becomes inactive. The
  * function switches to the new config object for persistent pools. Inactive
  * pools are removed.
  */
 static void
-virStoragePoolUpdateInactive(virStoragePoolObjPtr *objptr)
+virStoragePoolUpdateInactive(virStoragePoolObjPtr *objptr,
+                             const char *name)
 {
     virStoragePoolObjPtr obj = *objptr;
 
     if (!virStoragePoolObjGetConfigFile(obj)) {
-        virStoragePoolObjRemove(driver->pools, obj);
-        virObjectUnref(obj);
+        virStoragePoolObjEndAPI(&obj);
+        virStoragePoolObjRemove(driver->pools, name);
         *objptr = NULL;
     } else if (virStoragePoolObjGetNewDef(obj)) {
         virStoragePoolObjDefUseNewDef(obj);
@@ -110,6 +112,7 @@ storagePoolUpdateStateCallback(virStoragePoolObjPtr obj,
     bool active = false;
     virStorageBackendPtr backend;
     char *stateFile;
+    char *name = NULL;
 
     if (!(stateFile = virFileBuildPath(driver->stateDir, def->name, ".xml")))
         goto cleanup;
@@ -120,6 +123,9 @@ storagePoolUpdateStateCallback(virStoragePoolObjPtr obj,
         goto cleanup;
     }
 
+    if (VIR_STRDUP(name, def->name) < 0)
+        goto cleanup;
+
     /* Backends which do not support 'checkPool' are considered
      * inactive by default. */
     if (backend->checkPool &&
@@ -149,12 +155,13 @@ storagePoolUpdateStateCallback(virStoragePoolObjPtr obj,
     virStoragePoolObjSetActive(obj, active);
 
     if (!virStoragePoolObjIsActive(obj))
-        virStoragePoolUpdateInactive(&obj);
+        virStoragePoolUpdateInactive(&obj, name);
 
  cleanup:
     if (!active && stateFile)
         ignore_value(unlink(stateFile));
     VIR_FREE(stateFile);
+    VIR_FREE(name);
 
     return;
 }
@@ -707,6 +714,7 @@ storagePoolCreateXML(virConnectPtr conn,
     virStorageBackendPtr backend;
     virObjectEventPtr event = NULL;
     char *stateFile = NULL;
+    char *name = NULL;
     unsigned int build_flags = 0;
 
     virCheckFlags(VIR_STORAGE_POOL_CREATE_WITH_BUILD |
@@ -731,6 +739,9 @@ storagePoolCreateXML(virConnectPtr conn,
     if ((backend = virStorageBackendForType(newDef->type)) == NULL)
         goto cleanup;
 
+    if (VIR_STRDUP(name, newDef->name) < 0)
+        goto cleanup;
+
     if (!(obj = virStoragePoolObjAssignDef(driver->pools, newDef)))
         goto cleanup;
     newDef = NULL;
@@ -776,6 +787,7 @@ storagePoolCreateXML(virConnectPtr conn,
     pool = virGetStoragePool(conn, def->name, def->uuid, NULL, NULL);
 
  cleanup:
+    VIR_FREE(name);
     VIR_FREE(stateFile);
     virStoragePoolDefFree(newDef);
     if (event)
@@ -784,9 +796,8 @@ storagePoolCreateXML(virConnectPtr conn,
     return pool;
 
  error:
-    virStoragePoolObjRemove(driver->pools, obj);
-    virObjectUnref(obj);
-    obj = NULL;
+    virStoragePoolObjEndAPI(&obj);
+    virStoragePoolObjRemove(driver->pools, name);
     goto cleanup;
 }
 
@@ -800,6 +811,7 @@ storagePoolDefineXML(virConnectPtr conn,
     virStoragePoolDefPtr def;
     virStoragePoolPtr pool = NULL;
     virObjectEventPtr event = NULL;
+    char *name = NULL;
 
     virCheckFlags(0, NULL);
 
@@ -821,15 +833,17 @@ storagePoolDefineXML(virConnectPtr conn,
     if (virStorageBackendForType(newDef->type) == NULL)
         goto cleanup;
 
+    if (VIR_STRDUP(name, newDef->name) < 0)
+        goto cleanup;
+
     if (!(obj = virStoragePoolObjAssignDef(driver->pools, newDef)))
         goto cleanup;
     newDef = NULL;
     def = virStoragePoolObjGetDef(obj);
 
     if (virStoragePoolObjSaveDef(driver, obj, def) < 0) {
-        virStoragePoolObjRemove(driver->pools, obj);
-        virObjectUnref(obj);
-        obj = NULL;
+        virStoragePoolObjEndAPI(&obj);
+        virStoragePoolObjRemove(driver->pools, name);
         goto cleanup;
     }
 
@@ -841,6 +855,7 @@ storagePoolDefineXML(virConnectPtr conn,
     pool = virGetStoragePool(conn, def->name, def->uuid, NULL, NULL);
 
  cleanup:
+    VIR_FREE(name);
     if (event)
         virObjectEventStateQueue(driver->storageEventState, event);
     virStoragePoolDefFree(newDef);
@@ -895,9 +910,8 @@ storagePoolUndefine(virStoragePoolPtr pool)
                                             0);
 
     VIR_INFO("Undefining storage pool '%s'", def->name);
-    virStoragePoolObjRemove(driver->pools, obj);
-    virObjectUnref(obj);
-    obj = NULL;
+    virStoragePoolObjEndAPI(&obj);
+    virStoragePoolObjRemove(driver->pools, pool->name);
     ret = 0;
 
  cleanup:
@@ -1089,7 +1103,7 @@ storagePoolDestroy(virStoragePoolPtr pool)
 
     virStoragePoolObjSetActive(obj, false);
 
-    virStoragePoolUpdateInactive(&obj);
+    virStoragePoolUpdateInactive(&obj, pool->name);
 
     ret = 0;
 
@@ -1212,7 +1226,7 @@ storagePoolRefresh(virStoragePoolPtr pool,
                                                 0);
         virStoragePoolObjSetActive(obj, false);
 
-        virStoragePoolUpdateInactive(&obj);
+        virStoragePoolUpdateInactive(&obj, pool->name);
 
         goto cleanup;
     }
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 0a284e3d1..70509a204 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -4540,6 +4540,7 @@ testStoragePoolCreateXML(virConnectPtr conn,
     virStoragePoolDefPtr def;
     virStoragePoolPtr pool = NULL;
     virObjectEventPtr event = NULL;
+    char *name = NULL;
 
     virCheckFlags(0, NULL);
 
@@ -4550,6 +4551,9 @@ testStoragePoolCreateXML(virConnectPtr conn,
     if (virStoragePoolObjIsDuplicate(privconn->pools, newDef, true) < 0)
         goto cleanup;
 
+    if (VIR_STRDUP(name, newDef->name) < 0)
+        goto cleanup;
+
     if (!(obj = virStoragePoolObjAssignDef(privconn->pools, newDef)))
         goto cleanup;
     newDef = NULL;
@@ -4583,6 +4587,7 @@ testStoragePoolCreateXML(virConnectPtr conn,
     pool = virGetStoragePool(conn, def->name, def->uuid, NULL, NULL);
 
  cleanup:
+    VIR_FREE(name);
     virStoragePoolDefFree(newDef);
     testObjectEventQueue(privconn, event);
     virStoragePoolObjEndAPI(&obj);
@@ -4590,9 +4595,8 @@ testStoragePoolCreateXML(virConnectPtr conn,
     return pool;
 
  error:
-    virStoragePoolObjRemove(privconn->pools, obj);
-    virObjectUnref(obj);
-    obj = NULL;
+    virStoragePoolObjEndAPI(&obj);
+    virStoragePoolObjRemove(privconn->pools, name);
     goto cleanup;
 }
 
@@ -4608,6 +4612,7 @@ testStoragePoolDefineXML(virConnectPtr conn,
     virStoragePoolDefPtr def;
     virStoragePoolPtr pool = NULL;
     virObjectEventPtr event = NULL;
+    char *name = NULL;
 
     virCheckFlags(0, NULL);
 
@@ -4622,6 +4627,9 @@ testStoragePoolDefineXML(virConnectPtr conn,
     if (virStoragePoolObjIsDuplicate(privconn->pools, newDef, false) < 0)
         goto cleanup;
 
+    if (VIR_STRDUP(name, newDef->name) < 0)
+        goto cleanup;
+
     if (!(obj = virStoragePoolObjAssignDef(privconn->pools, newDef)))
         goto cleanup;
     newDef = NULL;
@@ -4632,15 +4640,15 @@ testStoragePoolDefineXML(virConnectPtr conn,
                                             0);
 
     if (testStoragePoolObjSetDefaults(obj) == -1) {
-        virStoragePoolObjRemove(privconn->pools, obj);
-        virObjectUnref(obj);
-        obj = NULL;
+        virStoragePoolObjEndAPI(&obj);
+        virStoragePoolObjRemove(privconn->pools, name);
         goto cleanup;
     }
 
     pool = virGetStoragePool(conn, def->name, def->uuid, NULL, NULL);
 
  cleanup:
+    VIR_FREE(name);
     virStoragePoolDefFree(newDef);
     testObjectEventQueue(privconn, event);
     virStoragePoolObjEndAPI(&obj);
@@ -4663,8 +4671,8 @@ testStoragePoolUndefine(virStoragePoolPtr pool)
                                             VIR_STORAGE_POOL_EVENT_UNDEFINED,
                                             0);
 
-    virStoragePoolObjRemove(privconn->pools, obj);
-    virObjectUnref(obj);
+    virStoragePoolObjEndAPI(&obj);
+    virStoragePoolObjRemove(privconn->pools, pool->name);
 
     testObjectEventQueue(privconn, event);
     return 0;
@@ -4757,10 +4765,10 @@ testStoragePoolDestroy(virStoragePoolPtr pool)
                                             0);
 
     if (!(virStoragePoolObjGetConfigFile(obj))) {
-        virStoragePoolObjRemove(privconn->pools, obj);
-        virObjectUnref(obj);
-        obj = NULL;
+        virStoragePoolObjEndAPI(&obj);
+        virStoragePoolObjRemove(privconn->pools, pool->name);
     }
+
     ret = 0;
 
  cleanup:
-- 
2.13.6

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list



[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]

  Powered by Linux