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 1522272009747736.9438829353422; Wed, 28 Mar 2018 14:20:09 -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 1E22C23E6DD; Wed, 28 Mar 2018 21:20:08 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id E37215C2E4; Wed, 28 Mar 2018 21:20:07 +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 395924CAA5; Wed, 28 Mar 2018 21:20:07 +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 w2SLJhOX000504 for ; Wed, 28 Mar 2018 17:19:43 -0400 Received: by smtp.corp.redhat.com (Postfix) id 0D1E563142; Wed, 28 Mar 2018 21:19:43 +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 C039963143 for ; Wed, 28 Mar 2018 21:19:42 +0000 (UTC) From: John Ferlan To: libvir-list@redhat.com Date: Wed, 28 Mar 2018 17:19:28 -0400 Message-Id: <20180328211933.8033-5-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 4/9] nodedev: Alter virNodeDeviceObjListRemove 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.29]); Wed, 28 Mar 2018 21:20:08 +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 @devs, and relocking @obj in order to ensure proper proper lock ordering. This can be avoided by changing virNodeDeviceObjListRemove to take @name instead of @obj. Then, we can lock the @devs 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/virnodedeviceobj.c | 29 +++++++++++++++++------------ src/conf/virnodedeviceobj.h | 2 +- src/node_device/node_device_hal.c | 16 +++++++++------- src/node_device/node_device_udev.c | 13 +++++++++---- src/test/test_driver.c | 28 ++++++++++++++-------------- 5 files changed, 50 insertions(+), 38 deletions(-) diff --git a/src/conf/virnodedeviceobj.c b/src/conf/virnodedeviceobj.c index ad0f27ee4..9064a6cfb 100644 --- a/src/conf/virnodedeviceobj.c +++ b/src/conf/virnodedeviceobj.c @@ -470,23 +470,28 @@ virNodeDeviceObjListAssignDef(virNodeDeviceObjListPtr= devs, } =20 =20 +/* + * virNodeDeviceObjListRemove: + * @devs: list of node device objects + * @name: a node device definition + * + * 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 virNodeDeviceObjListRemove(virNodeDeviceObjListPtr devs, - virNodeDeviceObjPtr obj) + const char *name) { - virNodeDeviceDefPtr def; - - if (!obj) - return; - def =3D obj->def; + virNodeDeviceObjPtr obj; =20 - virObjectRef(obj); - virObjectUnlock(obj); virObjectRWLockWrite(devs); - virObjectLock(obj); - virHashRemoveEntry(devs->objs, def->name); - virObjectUnlock(obj); - virObjectUnref(obj); + if ((obj =3D virNodeDeviceObjListFindByNameLocked(devs, name))) { + virHashRemoveEntry(devs->objs, name); + virNodeDeviceObjEndAPI(&obj); + } virObjectRWUnlock(devs); } =20 diff --git a/src/conf/virnodedeviceobj.h b/src/conf/virnodedeviceobj.h index 87f908369..b9752bc62 100644 --- a/src/conf/virnodedeviceobj.h +++ b/src/conf/virnodedeviceobj.h @@ -72,7 +72,7 @@ virNodeDeviceObjListAssignDef(virNodeDeviceObjListPtr dev= s, =20 void virNodeDeviceObjListRemove(virNodeDeviceObjListPtr devs, - virNodeDeviceObjPtr dev); + const char *name); =20 int virNodeDeviceObjListGetParentHost(virNodeDeviceObjListPtr devs, diff --git a/src/node_device/node_device_hal.c b/src/node_device/node_devic= e_hal.c index 6ad56f416..46a419a6e 100644 --- a/src/node_device/node_device_hal.c +++ b/src/node_device/node_device_hal.c @@ -511,8 +511,8 @@ dev_refresh(const char *udi) /* Simply "rediscover" device -- incrementally handling changes * to sub-capabilities (like net.80203) is nasty ... so avoid it. */ - virNodeDeviceObjListRemove(driver->devs, obj); - virObjectUnref(obj); + virNodeDeviceObjEndAPI(&obj); + virNodeDeviceObjListRemoveDef(driver->devs, name); dev_create(udi); } else { VIR_DEBUG("no device named %s", name); @@ -536,12 +536,14 @@ device_removed(LibHalContext *ctx ATTRIBUTE_UNUSED, virNodeDeviceObjPtr obj; =20 obj =3D virNodeDeviceObjListFindByName(driver->devs, name); - VIR_DEBUG("%s", name); - if (obj) - virNodeDeviceObjListRemove(driver->devs, obj); - else + if (!obj) { VIR_DEBUG("no device named %s", name); - virObjectUnref(obj); + return; + } + + VIR_DEBUG("%s", name); + virNodeDeviceObjEndAPI(&obj); + virNodeDeviceObjListRemove(driver->devs, name); } =20 =20 diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_devi= ce_udev.c index e87eb32a8..f6d223fe4 100644 --- a/src/node_device/node_device_udev.c +++ b/src/node_device/node_device_udev.c @@ -1282,6 +1282,7 @@ udevRemoveOneDevice(struct udev_device *device) virNodeDeviceDefPtr def; virObjectEventPtr event =3D NULL; const char *name =3D NULL; + char *defname =3D NULL; =20 name =3D udev_device_get_syspath(device); if (!(obj =3D virNodeDeviceObjListFindBySysfsPath(driver->devs, name))= ) { @@ -1290,15 +1291,19 @@ udevRemoveOneDevice(struct udev_device *device) return -1; } def =3D virNodeDeviceObjGetDef(obj); + if (VIR_STRDUP(defname, def->name) < 0) { + virNodeDeviceObjEndAPI(&obj); + return -1; + } =20 event =3D virNodeDeviceEventLifecycleNew(def->name, VIR_NODE_DEVICE_EVENT_DELETED, 0); =20 - VIR_DEBUG("Removing device '%s' with sysfs path '%s'", - def->name, name); - virNodeDeviceObjListRemove(driver->devs, obj); - virObjectUnref(obj); + VIR_DEBUG("Removing device '%s' with sysfs path '%s'", defname, name); + virNodeDeviceObjEndAPI(&obj); + virNodeDeviceObjListRemove(driver->devs, defname); + VIR_FREE(defname); =20 if (event) virObjectEventStateQueue(driver->nodeDeviceEventState, event); diff --git a/src/test/test_driver.c b/src/test/test_driver.c index ddddd8dcb..568d537e9 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -4723,8 +4723,8 @@ testDestroyVport(testDriverPtr privconn, VIR_NODE_DEVICE_EVENT_DELETED, 0); =20 - virNodeDeviceObjListRemove(privconn->devs, obj); - virObjectUnref(obj); + virNodeDeviceObjEndAPI(&obj); + virNodeDeviceObjListRemove(privconn->devs, "scsi_host12"); =20 testObjectEventQueue(privconn, event); return 0; @@ -5670,6 +5670,7 @@ testNodeDeviceDestroy(virNodeDevicePtr dev) virNodeDeviceObjPtr obj =3D NULL; virNodeDeviceObjPtr parentobj =3D NULL; virNodeDeviceDefPtr def; + char *parent =3D NULL; char *wwnn =3D NULL, *wwpn =3D NULL; virObjectEventPtr event =3D NULL; =20 @@ -5681,18 +5682,19 @@ testNodeDeviceDestroy(virNodeDevicePtr dev) goto cleanup; =20 /* Unlike the real code we cannot run into the udevAddOneDevice race - * which would replace obj->def, so no need to save off the parent, - * but do need to drop the @obj lock so that the FindByName code doesn= 't - * deadlock on ourselves */ - virObjectUnlock(obj); + * which would replace obj->def, but we still need to save off the + * parent name since we're about to Unref and Unlock the @obj containi= ng + * the @def so that we don't deadlock in virNodeDeviceObjListFindByNam= e. */ + if (VIR_STRDUP(parent, def->parent) < 0) + goto cleanup; + + virNodeDeviceObjEndAPI(&obj); =20 /* We do this just for basic validation and throw away the parentobj * since there's no vport_delete to be run */ - if (!(parentobj =3D virNodeDeviceObjListFindByName(driver->devs, - def->parent))) { + if (!(parentobj =3D virNodeDeviceObjListFindByName(driver->devs, paren= t))) { virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot find parent '%s' definition"), def->paren= t); - virObjectLock(obj); + _("cannot find parent '%s' definition"), parent); goto cleanup; } virNodeDeviceObjEndAPI(&parentobj); @@ -5701,16 +5703,14 @@ testNodeDeviceDestroy(virNodeDevicePtr dev) VIR_NODE_DEVICE_EVENT_DELETED, 0); =20 - virObjectLock(obj); - virNodeDeviceObjListRemove(driver->devs, obj); - virObjectUnref(obj); - obj =3D NULL; + virNodeDeviceObjListRemove(driver->devs, dev->name); =20 cleanup: virNodeDeviceObjEndAPI(&obj); testObjectEventQueue(driver, event); VIR_FREE(wwnn); VIR_FREE(wwpn); + VIR_FREE(parent); return ret; } =20 --=20 2.13.6 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list