From nobody Fri May 16 04:03:10 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 1500303758672879.8859902678973; Mon, 17 Jul 2017 08:02:38 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A73BE7A168; Mon, 17 Jul 2017 15:02:35 +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 765397B60B; Mon, 17 Jul 2017 15:02:35 +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 181053FAE0; Mon, 17 Jul 2017 15:02:35 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v6HF2YAO024583 for ; Mon, 17 Jul 2017 11:02:34 -0400 Received: by smtp.corp.redhat.com (Postfix) id 141A77E902; Mon, 17 Jul 2017 15:02:34 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-46.phx2.redhat.com [10.3.117.46]) by smtp.corp.redhat.com (Postfix) with ESMTP id B9C2D7EFC0 for ; Mon, 17 Jul 2017 15:02:31 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com A73BE7A168 Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=libvir-list-bounces@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com A73BE7A168 From: John Ferlan To: libvir-list@redhat.com Date: Mon, 17 Jul 2017 11:02:23 -0400 Message-Id: <20170717150224.2988-3-jferlan@redhat.com> In-Reply-To: <20170717150224.2988-1-jferlan@redhat.com> References: <20170717150224.2988-1-jferlan@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH v5 2/3] nodedev: Convert virNodeDeviceObjListPtr to use hash tables 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.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Mon, 17 Jul 2017 15:02:36 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Rather than use a forward linked list of elements, it'll be much more efficient to use a hash table to reference the elements by unique name and to perform hash searches. This patch does all the heavy lifting of converting the list object to use a self locking list that contains the hash table. Each of the FindBy functions that do not involve finding the object by it's key (name) is converted to use virHashSearch in order to find the specific object. When searching for the key (name), it's possible to use virHashLookup. For any of the list perusal functions that are required to evaluate each object, the virHashForEach function is used. Signed-off-by: John Ferlan --- src/conf/virnodedeviceobj.c | 575 ++++++++++++++++++++++++++++++----------= ---- 1 file changed, 400 insertions(+), 175 deletions(-) diff --git a/src/conf/virnodedeviceobj.c b/src/conf/virnodedeviceobj.c index 8416dda..acf88db 100644 --- a/src/conf/virnodedeviceobj.c +++ b/src/conf/virnodedeviceobj.c @@ -25,6 +25,7 @@ #include "viralloc.h" #include "virnodedeviceobj.h" #include "virerror.h" +#include "virhash.h" #include "virlog.h" #include "virstring.h" =20 @@ -39,13 +40,19 @@ struct _virNodeDeviceObj { }; =20 struct _virNodeDeviceObjList { - size_t count; - virNodeDeviceObjPtr *objs; + virObjectLockable parent; + + /* name string -> virNodeDeviceObj mapping + * for O(1), lockless lookup-by-uuid */ + virHashTable *objs; + }; =20 =20 static virClassPtr virNodeDeviceObjClass; +static virClassPtr virNodeDeviceObjListClass; static void virNodeDeviceObjDispose(void *opaque); +static void virNodeDeviceObjListDispose(void *opaque); =20 static int virNodeDeviceObjOnceInit(void) @@ -56,6 +63,12 @@ virNodeDeviceObjOnceInit(void) virNodeDeviceObjDispose))) return -1; =20 + if (!(virNodeDeviceObjListClass =3D virClassNew(virClassForObjectLocka= ble(), + "virNodeDeviceObjList", + sizeof(virNodeDeviceObjL= ist), + virNodeDeviceObjListDisp= ose))) + return -1; + return 0; } =20 @@ -211,26 +224,49 @@ virNodeDeviceFindVPORTCapDef(const virNodeDeviceObj *= obj) } =20 =20 +static int +virNodeDeviceObjListFindBySysfsPathCallback(const void *payload, + const void *name ATTRIBUTE_UNU= SED, + const void *opaque) +{ + virNodeDeviceObjPtr obj =3D (virNodeDeviceObjPtr) payload; + virNodeDeviceDefPtr def; + const char *sysfs_path =3D opaque; + int want =3D 0; + + virObjectLock(obj); + def =3D obj->def; + if (STREQ_NULLABLE(def->sysfs_path, sysfs_path)) + want =3D 1; + virObjectUnlock(obj); + return want; +} + + virNodeDeviceObjPtr virNodeDeviceObjListFindBySysfsPath(virNodeDeviceObjListPtr devs, const char *sysfs_path) { - size_t i; + virNodeDeviceObjPtr obj; =20 - for (i =3D 0; i < devs->count; i++) { - virNodeDeviceObjPtr obj =3D devs->objs[i]; - virNodeDeviceDefPtr def; + virObjectLock(devs); + obj =3D virHashSearch(devs->objs, virNodeDeviceObjListFindBySysfsPathC= allback, + (void *)sysfs_path); + virObjectRef(obj); + virObjectUnlock(devs); =20 + if (obj) virObjectLock(obj); - def =3D obj->def; - if ((def->sysfs_path !=3D NULL) && - (STREQ(def->sysfs_path, sysfs_path))) { - return virObjectRef(obj); - } - virObjectUnlock(obj); - } =20 - return NULL; + return obj; +} + + +static virNodeDeviceObjPtr +virNodeDeviceObjListFindByNameLocked(virNodeDeviceObjListPtr devs, + const char *name) +{ + return virObjectRef(virHashLookup(devs->objs, name)); } =20 =20 @@ -238,20 +274,42 @@ virNodeDeviceObjPtr virNodeDeviceObjListFindByName(virNodeDeviceObjListPtr devs, const char *name) { - size_t i; - - for (i =3D 0; i < devs->count; i++) { - virNodeDeviceObjPtr obj =3D devs->objs[i]; - virNodeDeviceDefPtr def; + virNodeDeviceObjPtr obj; =20 + virObjectLock(devs); + obj =3D virNodeDeviceObjListFindByNameLocked(devs, name); + virObjectUnlock(devs); + if (obj) virObjectLock(obj); - def =3D obj->def; - if (STREQ(def->name, name)) - return virObjectRef(obj); - virObjectUnlock(obj); - } =20 - return NULL; + return obj; +} + + +struct virNodeDeviceObjListFindByWWNsData { + const char *parent_wwnn; + const char *parent_wwpn; +}; + +static int +virNodeDeviceObjListFindByWWNsCallback(const void *payload, + const void *name ATTRIBUTE_UNUSED, + const void *opaque) +{ + virNodeDeviceObjPtr obj =3D (virNodeDeviceObjPtr) payload; + struct virNodeDeviceObjListFindByWWNsData *data =3D + (struct virNodeDeviceObjListFindByWWNsData *) opaque; + virNodeDevCapsDefPtr cap; + int want =3D 0; + + virObjectLock(obj); + if ((cap =3D virNodeDeviceFindFCCapDef(obj)) && + STREQ_NULLABLE(cap->data.scsi_host.wwnn, data->parent_wwnn) && + STREQ_NULLABLE(cap->data.scsi_host.wwpn, data->parent_wwpn) && + virNodeDeviceFindVPORTCapDef(obj)) + want =3D 1; + virObjectUnlock(obj); + return want; } =20 =20 @@ -260,22 +318,40 @@ virNodeDeviceObjListFindByWWNs(virNodeDeviceObjListPt= r devs, const char *parent_wwnn, const char *parent_wwpn) { - size_t i; + virNodeDeviceObjPtr obj; + struct virNodeDeviceObjListFindByWWNsData data =3D { + .parent_wwnn =3D parent_wwnn, .parent_wwpn =3D parent_wwpn }; =20 - for (i =3D 0; i < devs->count; i++) { - virNodeDeviceObjPtr obj =3D devs->objs[i]; - virNodeDevCapsDefPtr cap; + virObjectLock(devs); + obj =3D virHashSearch(devs->objs, virNodeDeviceObjListFindByWWNsCallba= ck, + &data); + virObjectRef(obj); + virObjectUnlock(devs); =20 + if (obj) virObjectLock(obj); - if ((cap =3D virNodeDeviceFindFCCapDef(obj)) && - STREQ_NULLABLE(cap->data.scsi_host.wwnn, parent_wwnn) && - STREQ_NULLABLE(cap->data.scsi_host.wwpn, parent_wwpn) && - virNodeDeviceFindVPORTCapDef(obj)) - return virObjectRef(obj); - virObjectUnlock(obj); - } =20 - return NULL; + return obj; +} + + +static int +virNodeDeviceObjListFindByFabricWWNCallback(const void *payload, + const void *name ATTRIBUTE_UNU= SED, + const void *opaque) +{ + virNodeDeviceObjPtr obj =3D (virNodeDeviceObjPtr) payload; + const char *matchstr =3D opaque; + virNodeDevCapsDefPtr cap; + int want =3D 0; + + virObjectLock(obj); + if ((cap =3D virNodeDeviceFindFCCapDef(obj)) && + STREQ_NULLABLE(cap->data.scsi_host.fabric_wwn, matchstr) && + virNodeDeviceFindVPORTCapDef(obj)) + want =3D 1; + virObjectUnlock(obj); + return want; } =20 =20 @@ -283,21 +359,35 @@ static virNodeDeviceObjPtr virNodeDeviceObjListFindByFabricWWN(virNodeDeviceObjListPtr devs, const char *parent_fabric_wwn) { - size_t i; + virNodeDeviceObjPtr obj; =20 - for (i =3D 0; i < devs->count; i++) { - virNodeDeviceObjPtr obj =3D devs->objs[i]; - virNodeDevCapsDefPtr cap; + virObjectLock(devs); + obj =3D virHashSearch(devs->objs, virNodeDeviceObjListFindByFabricWWNC= allback, + (void *)parent_fabric_wwn); + virObjectRef(obj); + virObjectUnlock(devs); =20 + if (obj) virObjectLock(obj); - if ((cap =3D virNodeDeviceFindFCCapDef(obj)) && - STREQ_NULLABLE(cap->data.scsi_host.fabric_wwn, parent_fabric_w= wn) && - virNodeDeviceFindVPORTCapDef(obj)) - return virObjectRef(obj); - virObjectUnlock(obj); - } =20 - return NULL; + return obj; +} + + +static int +virNodeDeviceObjListFindByCapCallback(const void *payload, + const void *name ATTRIBUTE_UNUSED, + const void *opaque) +{ + virNodeDeviceObjPtr obj =3D (virNodeDeviceObjPtr) payload; + const char *matchstr =3D opaque; + int want =3D 0; + + virObjectLock(obj); + if (virNodeDeviceObjHasCap(obj, matchstr)) + want =3D 1; + virObjectUnlock(obj); + return want; } =20 =20 @@ -305,18 +395,59 @@ static virNodeDeviceObjPtr virNodeDeviceObjListFindByCap(virNodeDeviceObjListPtr devs, const char *cap) { - size_t i; + virNodeDeviceObjPtr obj; =20 - for (i =3D 0; i < devs->count; i++) { - virNodeDeviceObjPtr obj =3D devs->objs[i]; + virObjectLock(devs); + obj =3D virHashSearch(devs->objs, virNodeDeviceObjListFindByCapCallbac= k, + (void *)cap); + virObjectRef(obj); + virObjectUnlock(devs); =20 + if (obj) virObjectLock(obj); - if (virNodeDeviceObjHasCap(obj, cap)) - return virObjectRef(obj); - virObjectUnlock(obj); - } =20 - return NULL; + return obj; +} + + +struct virNodeDeviceObjListFindSCSIHostByWWNsData { + const char *wwnn; + const char *wwpn; +}; + +static int +virNodeDeviceObjListFindSCSIHostByWWNsCallback(const void *payload, + const void *name ATTRIBUTE_= UNUSED, + const void *opaque) +{ + virNodeDeviceObjPtr obj =3D (virNodeDeviceObjPtr) payload; + virNodeDeviceDefPtr def; + struct virNodeDeviceObjListFindSCSIHostByWWNsData *data =3D + (struct virNodeDeviceObjListFindSCSIHostByWWNsData *) opaque; + virNodeDevCapsDefPtr cap; + int want =3D 0; + + virObjectLock(obj); + def =3D obj->def; + cap =3D def->caps; + + while (cap) { + if (cap->data.type =3D=3D VIR_NODE_DEV_CAP_SCSI_HOST) { + virNodeDeviceGetSCSIHostCaps(&cap->data.scsi_host); + if (cap->data.scsi_host.flags & + VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST) { + if (STREQ(cap->data.scsi_host.wwnn, data->wwnn) && + STREQ(cap->data.scsi_host.wwpn, data->wwpn)) { + want =3D 1; + break; + } + } + } + cap =3D cap->next; + } + + virObjectUnlock(obj); + return want; } =20 =20 @@ -325,31 +456,30 @@ virNodeDeviceObjListFindSCSIHostByWWNs(virNodeDeviceO= bjListPtr devs, const char *wwnn, const char *wwpn) { - size_t i; + virNodeDeviceObjPtr obj; + struct virNodeDeviceObjListFindSCSIHostByWWNsData data =3D { + .wwnn =3D wwnn, .wwpn =3D wwpn }; =20 - for (i =3D 0; i < devs->count; i++) { - virNodeDeviceObjPtr obj =3D devs->objs[i]; - virNodeDevCapsDefPtr cap; + virObjectLock(devs); + obj =3D virHashSearch(devs->objs, + virNodeDeviceObjListFindSCSIHostByWWNsCallback, + &data); + virObjectRef(obj); + virObjectUnlock(devs); =20 + if (obj) virObjectLock(obj); - cap =3D obj->def->caps; - - while (cap) { - if (cap->data.type =3D=3D VIR_NODE_DEV_CAP_SCSI_HOST) { - virNodeDeviceGetSCSIHostCaps(&cap->data.scsi_host); - if (cap->data.scsi_host.flags & - VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST) { - if (STREQ(cap->data.scsi_host.wwnn, wwnn) && - STREQ(cap->data.scsi_host.wwpn, wwpn)) - return virObjectRef(obj); - } - } - cap =3D cap->next; - } - virObjectUnlock(obj); - } =20 - return NULL; + return obj; +} + + +static void +virNodeDeviceObjListDispose(void *obj) +{ + virNodeDeviceObjListPtr devs =3D obj; + + virHashFree(devs->objs); } =20 =20 @@ -358,8 +488,17 @@ virNodeDeviceObjListNew(void) { virNodeDeviceObjListPtr devs; =20 - if (VIR_ALLOC(devs) < 0) + if (virNodeDeviceObjInitialize() < 0) + return NULL; + + if (!(devs =3D virObjectLockableNew(virNodeDeviceObjListClass))) return NULL; + + if (!(devs->objs =3D virHashCreate(50, virObjectFreeHashData))) { + virObjectUnref(devs); + return NULL; + } + return devs; } =20 @@ -367,11 +506,7 @@ virNodeDeviceObjListNew(void) void virNodeDeviceObjListFree(virNodeDeviceObjListPtr devs) { - size_t i; - for (i =3D 0; i < devs->count; i++) - virObjectUnref(devs->objs[i]); - VIR_FREE(devs->objs); - VIR_FREE(devs); + virObjectUnref(devs); } =20 =20 @@ -381,22 +516,28 @@ virNodeDeviceObjListAssignDef(virNodeDeviceObjListPtr= devs, { virNodeDeviceObjPtr obj; =20 - if ((obj =3D virNodeDeviceObjListFindByName(devs, def->name))) { + virObjectLock(devs); + + if ((obj =3D virNodeDeviceObjListFindByNameLocked(devs, def->name))) { + virObjectLock(obj); virNodeDeviceDefFree(obj->def); obj->def =3D def; - return obj; - } + } else { + if (!(obj =3D virNodeDeviceObjNew())) + goto cleanup; =20 - if (!(obj =3D virNodeDeviceObjNew())) - return NULL; + if (virHashAddEntry(devs->objs, def->name, obj) < 0) { + virNodeDeviceObjEndAPI(&obj); + goto cleanup; + } =20 - if (VIR_APPEND_ELEMENT_COPY(devs->objs, devs->count, obj) < 0) { - virNodeDeviceObjEndAPI(&obj); - return NULL; + obj->def =3D def; + virObjectRef(obj); } - obj->def =3D def; =20 - return virObjectRef(obj); + cleanup: + virObjectUnlock(devs); + return obj; } =20 =20 @@ -404,21 +545,20 @@ void virNodeDeviceObjListRemove(virNodeDeviceObjListPtr devs, virNodeDeviceObjPtr obj) { - size_t i; - - virObjectUnlock(obj); + virNodeDeviceDefPtr def; =20 - for (i =3D 0; i < devs->count; i++) { - virObjectLock(devs->objs[i]); - if (devs->objs[i] =3D=3D obj) { - virObjectUnlock(devs->objs[i]); - virObjectUnref(devs->objs[i]); + if (!obj) + return; + def =3D obj->def; =20 - VIR_DELETE_ELEMENT(devs->objs, i, devs->count); - break; - } - virObjectUnlock(devs->objs[i]); - } + virObjectRef(obj); + virObjectUnlock(obj); + virObjectLock(devs); + virObjectLock(obj); + virHashRemoveEntry(devs->objs, def->name); + virObjectUnlock(obj); + virObjectUnref(obj); + virObjectUnlock(devs); } =20 =20 @@ -643,25 +783,89 @@ virNodeDeviceCapMatch(virNodeDeviceObjPtr obj, } =20 =20 +struct virNodeDeviceCountData { + virConnectPtr conn; + virNodeDeviceObjListFilter aclfilter; + const char *matchstr; + int count; +}; + +static int +virNodeDeviceObjListNumOfDevicesCallback(void *payload, + const void *name ATTRIBUTE_UNUSED, + void *opaque) +{ + virNodeDeviceObjPtr obj =3D payload; + virNodeDeviceDefPtr def; + struct virNodeDeviceCountData *data =3D opaque; + virNodeDeviceObjListFilter aclfilter =3D data->aclfilter; + + virObjectLock(obj); + def =3D obj->def; + if ((!aclfilter || aclfilter(data->conn, def)) && + (!data->matchstr || virNodeDeviceObjHasCap(obj, data->matchstr))) + data->count++; + + virObjectUnlock(obj); + return 0; +} + + int virNodeDeviceObjListNumOfDevices(virNodeDeviceObjListPtr devs, virConnectPtr conn, const char *cap, virNodeDeviceObjListFilter aclfilter) { - size_t i; - int ndevs =3D 0; + struct virNodeDeviceCountData data =3D { + .conn =3D conn, .aclfilter =3D aclfilter, .matchstr =3D cap, .coun= t =3D 0 }; =20 - for (i =3D 0; i < devs->count; i++) { - virNodeDeviceObjPtr obj =3D devs->objs[i]; - virObjectLock(obj); - if ((!aclfilter || aclfilter(conn, obj->def)) && - (!cap || virNodeDeviceObjHasCap(obj, cap))) - ++ndevs; - virObjectUnlock(obj); - } + virObjectLock(devs); + virHashForEach(devs->objs, virNodeDeviceObjListNumOfDevicesCallback, &= data); + virObjectUnlock(devs); + + return data.count; +} + + +struct virNodeDeviceGetNamesData { + virConnectPtr conn; + virNodeDeviceObjListFilter aclfilter; + const char *matchstr; + int nnames; + char **names; + int maxnames; + bool error; +}; + +static int +virNodeDeviceObjListGetNamesCallback(void *payload, + const void *name ATTRIBUTE_UNUSED, + void *opaque) +{ + virNodeDeviceObjPtr obj =3D payload; + virNodeDeviceDefPtr def; + struct virNodeDeviceGetNamesData *data =3D opaque; + virNodeDeviceObjListFilter aclfilter =3D data->aclfilter; + + if (data->error) + return 0; =20 - return ndevs; + virObjectLock(obj); + def =3D obj->def; + + if ((!aclfilter || aclfilter(data->conn, def)) && + (!data->matchstr || virNodeDeviceObjHasCap(obj, data->matchstr))) { + if (VIR_STRDUP(data->names[data->nnames], def->name) < 0) { + data->error =3D true; + goto cleanup; + } + data->nnames++; + } + + cleanup: + virObjectUnlock(obj); + return 0; } =20 =20 @@ -673,28 +877,22 @@ virNodeDeviceObjListGetNames(virNodeDeviceObjListPtr = devs, char **const names, int maxnames) { - int nnames =3D 0; - size_t i; + struct virNodeDeviceGetNamesData data =3D { + .conn =3D conn, .aclfilter =3D aclfilter, .matchstr =3D cap, .name= s =3D names, + .nnames =3D 0, .maxnames =3D maxnames, .error =3D false }; =20 - for (i =3D 0; i < devs->count && nnames < maxnames; i++) { - virNodeDeviceObjPtr obj =3D devs->objs[i]; - virObjectLock(obj); - if ((!aclfilter || aclfilter(conn, obj->def)) && - (!cap || virNodeDeviceObjHasCap(obj, cap))) { - if (VIR_STRDUP(names[nnames], obj->def->name) < 0) { - virObjectUnlock(obj); - goto failure; - } - nnames++; - } - virObjectUnlock(obj); - } + virObjectLock(devs); + virHashForEach(devs->objs, virNodeDeviceObjListGetNamesCallback, &data= ); + virObjectUnlock(devs); + + if (data.error) + goto error; =20 - return nnames; + return data.nnames; =20 - failure: - while (--nnames >=3D 0) - VIR_FREE(names[nnames]); + error: + while (--data.nnames) + VIR_FREE(data.names[data.nnames]); return -1; } =20 @@ -731,6 +929,51 @@ virNodeDeviceMatch(virNodeDeviceObjPtr obj, #undef MATCH =20 =20 +struct virNodeDeviceObjListExportData { + virConnectPtr conn; + virNodeDeviceObjListFilter aclfilter; + unsigned int flags; + virNodeDevicePtr *devices; + int ndevices; + bool error; +}; + +static int +virNodeDeviceObjListExportCallback(void *payload, + const void *name ATTRIBUTE_UNUSED, + void *opaque) +{ + virNodeDeviceObjPtr obj =3D payload; + virNodeDeviceDefPtr def; + struct virNodeDeviceObjListExportData *data =3D opaque; + virNodeDevicePtr device =3D NULL; + + if (data->error) + return 0; + + virObjectLock(obj); + def =3D obj->def; + + if ((!data->aclfilter || data->aclfilter(data->conn, def)) && + virNodeDeviceMatch(obj, data->flags)) { + if (data->devices) { + if (!(device =3D virGetNodeDevice(data->conn, def->name)) || + VIR_STRDUP(device->parent, def->parent) < 0) { + virObjectUnref(device); + data->error =3D true; + goto cleanup; + } + data->devices[data->ndevices] =3D device; + } + data->ndevices++; + } + + cleanup: + virObjectUnlock(obj); + return 0; +} + + int virNodeDeviceObjListExport(virConnectPtr conn, virNodeDeviceObjListPtr devs, @@ -738,49 +981,31 @@ virNodeDeviceObjListExport(virConnectPtr conn, virNodeDeviceObjListFilter aclfilter, unsigned int flags) { - virNodeDevicePtr *tmp_devices =3D NULL; - virNodeDevicePtr device =3D NULL; - int ndevices =3D 0; - int ret =3D -1; - size_t i; + struct virNodeDeviceObjListExportData data =3D { + .conn =3D conn, .aclfilter =3D aclfilter, .flags =3D flags, + .devices =3D NULL, .ndevices =3D 0, .error =3D false }; + + virObjectLock(devs); + if (devices && + VIR_ALLOC_N(data.devices, virHashSize(devs->objs) + 1) < 0) { + virObjectUnlock(devs); + return -1; + } =20 - if (devices && VIR_ALLOC_N(tmp_devices, devs->count + 1) < 0) - goto cleanup; + virHashForEach(devs->objs, virNodeDeviceObjListExportCallback, &data); + virObjectUnlock(devs); =20 - for (i =3D 0; i < devs->count; i++) { - virNodeDeviceObjPtr obj =3D devs->objs[i]; - virObjectLock(obj); - if ((!aclfilter || aclfilter(conn, obj->def)) && - virNodeDeviceMatch(obj, flags)) { - if (devices) { - if (!(device =3D virGetNodeDevice(conn, obj->def->name)) || - VIR_STRDUP(device->parent, obj->def->parent) < 0) { - virObjectUnref(device); - virObjectUnlock(obj); - goto cleanup; - } - tmp_devices[ndevices] =3D device; - } - ndevices++; - } - virObjectUnlock(obj); - } + if (data.error) + goto cleanup; =20 - if (tmp_devices) { - /* trim the array to the final size */ - ignore_value(VIR_REALLOC_N(tmp_devices, ndevices + 1)); - *devices =3D tmp_devices; - tmp_devices =3D NULL; - } + if (data.devices) { + ignore_value(VIR_REALLOC_N(data.devices, data.ndevices + 1)); + *devices =3D data.devices; + } =20 - ret =3D ndevices; + return data.ndevices; =20 cleanup: - if (tmp_devices) { - for (i =3D 0; i < ndevices; i++) - virObjectUnref(tmp_devices[i]); - } - - VIR_FREE(tmp_devices); - return ret; + virObjectListFree(data.devices); + return -1; } --=20 2.9.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list