From nobody Wed May 14 15:45:57 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1522272021102202.45618106946722; Wed, 28 Mar 2018 14:20:21 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id CD3747FD47; Wed, 28 Mar 2018 21:20:19 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 9EF2953B2F; Wed, 28 Mar 2018 21:20:19 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 64334180BAD6; Wed, 28 Mar 2018 21:20:19 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w2SLJjd3000540 for ; Wed, 28 Mar 2018 17:19:45 -0400 Received: by smtp.corp.redhat.com (Postfix) id 2D87463143; Wed, 28 Mar 2018 21:19:45 +0000 (UTC) Received: from unknown54ee7586bd10.attlocal.net.com (ovpn-116-109.phx2.redhat.com [10.3.116.109]) by smtp.corp.redhat.com (Postfix) with ESMTP id E1C8063142 for ; Wed, 28 Mar 2018 21:19:44 +0000 (UTC) From: John Ferlan To: libvir-list@redhat.com Date: Wed, 28 Mar 2018 17:19:33 -0400 Message-Id: <20180328211933.8033-10-jferlan@redhat.com> In-Reply-To: <20180328211933.8033-1-jferlan@redhat.com> References: <20180328211933.8033-1-jferlan@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH v2 9/9] storagepool: Alter virStoragePoolObjRemove processing X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Wed, 28 Mar 2018 21:20:20 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" 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 --- 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 con= n, } =20 =20 +/* + * 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]; =20 - 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 =3D virStoragePoolObjFindByNameLocked(pools, name))) { + virUUIDFormat(obj->def->uuid, uuidstr); + virHashRemoveEntry(pools->objs, uuidstr); + virHashRemoveEntry(pools->objsName, name); + virStoragePoolObjEndAPI(&obj); + } virObjectRWUnlock(pools); } =20 @@ -1117,6 +1127,7 @@ virStoragePoolObjLoad(virStoragePoolObjListPtr pools, { virStoragePoolDefPtr def =3D NULL; virStoragePoolObjPtr obj =3D NULL; + char *name =3D NULL; =20 if (!(def =3D virStoragePoolDefParseFile(path))) return NULL; @@ -1129,6 +1140,9 @@ virStoragePoolObjLoad(virStoragePoolObjListPtr pools, goto error; } =20 + if (VIR_STRDUP(name, def->name) < 0) + goto error; + if (!(obj =3D virStoragePoolObjAssignDef(pools, def))) goto error; def =3D NULL; @@ -1144,13 +1158,16 @@ virStoragePoolObjLoad(virStoragePoolObjListPtr pool= s, obj->autostart =3D virFileLinkPointsTo(obj->autostartLink, obj->configFile); =20 + VIR_FREE(name); + return obj; =20 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); =20 void virStoragePoolObjRemove(virStoragePoolObjListPtr pools, - virStoragePoolObjPtr obj); + const char *name); =20 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. T= he * function switches to the new config object for persistent pools. Inacti= ve * pools are removed. */ static void -virStoragePoolUpdateInactive(virStoragePoolObjPtr *objptr) +virStoragePoolUpdateInactive(virStoragePoolObjPtr *objptr, + const char *name) { virStoragePoolObjPtr obj =3D *objptr; =20 if (!virStoragePoolObjGetConfigFile(obj)) { - virStoragePoolObjRemove(driver->pools, obj); - virObjectUnref(obj); + virStoragePoolObjEndAPI(&obj); + virStoragePoolObjRemove(driver->pools, name); *objptr =3D NULL; } else if (virStoragePoolObjGetNewDef(obj)) { virStoragePoolObjDefUseNewDef(obj); @@ -110,6 +112,7 @@ storagePoolUpdateStateCallback(virStoragePoolObjPtr obj, bool active =3D false; virStorageBackendPtr backend; char *stateFile; + char *name =3D NULL; =20 if (!(stateFile =3D virFileBuildPath(driver->stateDir, def->name, ".xm= l"))) goto cleanup; @@ -120,6 +123,9 @@ storagePoolUpdateStateCallback(virStoragePoolObjPtr obj, goto cleanup; } =20 + 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 o= bj, virStoragePoolObjSetActive(obj, active); =20 if (!virStoragePoolObjIsActive(obj)) - virStoragePoolUpdateInactive(&obj); + virStoragePoolUpdateInactive(&obj, name); =20 cleanup: if (!active && stateFile) ignore_value(unlink(stateFile)); VIR_FREE(stateFile); + VIR_FREE(name); =20 return; } @@ -707,6 +714,7 @@ storagePoolCreateXML(virConnectPtr conn, virStorageBackendPtr backend; virObjectEventPtr event =3D NULL; char *stateFile =3D NULL; + char *name =3D NULL; unsigned int build_flags =3D 0; =20 virCheckFlags(VIR_STORAGE_POOL_CREATE_WITH_BUILD | @@ -731,6 +739,9 @@ storagePoolCreateXML(virConnectPtr conn, if ((backend =3D virStorageBackendForType(newDef->type)) =3D=3D NULL) goto cleanup; =20 + if (VIR_STRDUP(name, newDef->name) < 0) + goto cleanup; + if (!(obj =3D virStoragePoolObjAssignDef(driver->pools, newDef))) goto cleanup; newDef =3D NULL; @@ -776,6 +787,7 @@ storagePoolCreateXML(virConnectPtr conn, pool =3D virGetStoragePool(conn, def->name, def->uuid, NULL, NULL); =20 cleanup: + VIR_FREE(name); VIR_FREE(stateFile); virStoragePoolDefFree(newDef); if (event) @@ -784,9 +796,8 @@ storagePoolCreateXML(virConnectPtr conn, return pool; =20 error: - virStoragePoolObjRemove(driver->pools, obj); - virObjectUnref(obj); - obj =3D NULL; + virStoragePoolObjEndAPI(&obj); + virStoragePoolObjRemove(driver->pools, name); goto cleanup; } =20 @@ -800,6 +811,7 @@ storagePoolDefineXML(virConnectPtr conn, virStoragePoolDefPtr def; virStoragePoolPtr pool =3D NULL; virObjectEventPtr event =3D NULL; + char *name =3D NULL; =20 virCheckFlags(0, NULL); =20 @@ -821,15 +833,17 @@ storagePoolDefineXML(virConnectPtr conn, if (virStorageBackendForType(newDef->type) =3D=3D NULL) goto cleanup; =20 + if (VIR_STRDUP(name, newDef->name) < 0) + goto cleanup; + if (!(obj =3D virStoragePoolObjAssignDef(driver->pools, newDef))) goto cleanup; newDef =3D NULL; def =3D virStoragePoolObjGetDef(obj); =20 if (virStoragePoolObjSaveDef(driver, obj, def) < 0) { - virStoragePoolObjRemove(driver->pools, obj); - virObjectUnref(obj); - obj =3D NULL; + virStoragePoolObjEndAPI(&obj); + virStoragePoolObjRemove(driver->pools, name); goto cleanup; } =20 @@ -841,6 +855,7 @@ storagePoolDefineXML(virConnectPtr conn, pool =3D virGetStoragePool(conn, def->name, def->uuid, NULL, NULL); =20 cleanup: + VIR_FREE(name); if (event) virObjectEventStateQueue(driver->storageEventState, event); virStoragePoolDefFree(newDef); @@ -895,9 +910,8 @@ storagePoolUndefine(virStoragePoolPtr pool) 0); =20 VIR_INFO("Undefining storage pool '%s'", def->name); - virStoragePoolObjRemove(driver->pools, obj); - virObjectUnref(obj); - obj =3D NULL; + virStoragePoolObjEndAPI(&obj); + virStoragePoolObjRemove(driver->pools, pool->name); ret =3D 0; =20 cleanup: @@ -1089,7 +1103,7 @@ storagePoolDestroy(virStoragePoolPtr pool) =20 virStoragePoolObjSetActive(obj, false); =20 - virStoragePoolUpdateInactive(&obj); + virStoragePoolUpdateInactive(&obj, pool->name); =20 ret =3D 0; =20 @@ -1212,7 +1226,7 @@ storagePoolRefresh(virStoragePoolPtr pool, 0); virStoragePoolObjSetActive(obj, false); =20 - virStoragePoolUpdateInactive(&obj); + virStoragePoolUpdateInactive(&obj, pool->name); =20 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 =3D NULL; virObjectEventPtr event =3D NULL; + char *name =3D NULL; =20 virCheckFlags(0, NULL); =20 @@ -4550,6 +4551,9 @@ testStoragePoolCreateXML(virConnectPtr conn, if (virStoragePoolObjIsDuplicate(privconn->pools, newDef, true) < 0) goto cleanup; =20 + if (VIR_STRDUP(name, newDef->name) < 0) + goto cleanup; + if (!(obj =3D virStoragePoolObjAssignDef(privconn->pools, newDef))) goto cleanup; newDef =3D NULL; @@ -4583,6 +4587,7 @@ testStoragePoolCreateXML(virConnectPtr conn, pool =3D virGetStoragePool(conn, def->name, def->uuid, NULL, NULL); =20 cleanup: + VIR_FREE(name); virStoragePoolDefFree(newDef); testObjectEventQueue(privconn, event); virStoragePoolObjEndAPI(&obj); @@ -4590,9 +4595,8 @@ testStoragePoolCreateXML(virConnectPtr conn, return pool; =20 error: - virStoragePoolObjRemove(privconn->pools, obj); - virObjectUnref(obj); - obj =3D NULL; + virStoragePoolObjEndAPI(&obj); + virStoragePoolObjRemove(privconn->pools, name); goto cleanup; } =20 @@ -4608,6 +4612,7 @@ testStoragePoolDefineXML(virConnectPtr conn, virStoragePoolDefPtr def; virStoragePoolPtr pool =3D NULL; virObjectEventPtr event =3D NULL; + char *name =3D NULL; =20 virCheckFlags(0, NULL); =20 @@ -4622,6 +4627,9 @@ testStoragePoolDefineXML(virConnectPtr conn, if (virStoragePoolObjIsDuplicate(privconn->pools, newDef, false) < 0) goto cleanup; =20 + if (VIR_STRDUP(name, newDef->name) < 0) + goto cleanup; + if (!(obj =3D virStoragePoolObjAssignDef(privconn->pools, newDef))) goto cleanup; newDef =3D NULL; @@ -4632,15 +4640,15 @@ testStoragePoolDefineXML(virConnectPtr conn, 0); =20 if (testStoragePoolObjSetDefaults(obj) =3D=3D -1) { - virStoragePoolObjRemove(privconn->pools, obj); - virObjectUnref(obj); - obj =3D NULL; + virStoragePoolObjEndAPI(&obj); + virStoragePoolObjRemove(privconn->pools, name); goto cleanup; } =20 pool =3D virGetStoragePool(conn, def->name, def->uuid, NULL, NULL); =20 cleanup: + VIR_FREE(name); virStoragePoolDefFree(newDef); testObjectEventQueue(privconn, event); virStoragePoolObjEndAPI(&obj); @@ -4663,8 +4671,8 @@ testStoragePoolUndefine(virStoragePoolPtr pool) VIR_STORAGE_POOL_EVENT_UNDEFIN= ED, 0); =20 - virStoragePoolObjRemove(privconn->pools, obj); - virObjectUnref(obj); + virStoragePoolObjEndAPI(&obj); + virStoragePoolObjRemove(privconn->pools, pool->name); =20 testObjectEventQueue(privconn, event); return 0; @@ -4757,10 +4765,10 @@ testStoragePoolDestroy(virStoragePoolPtr pool) 0); =20 if (!(virStoragePoolObjGetConfigFile(obj))) { - virStoragePoolObjRemove(privconn->pools, obj); - virObjectUnref(obj); - obj =3D NULL; + virStoragePoolObjEndAPI(&obj); + virStoragePoolObjRemove(privconn->pools, pool->name); } + ret =3D 0; =20 cleanup: --=20 2.13.6 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list