diff --git a/po/POTFILES.in b/po/POTFILES.in index 9f66697d73..7c7f530782 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -42,6 +42,7 @@ src/conf/snapshot_conf.c src/conf/storage_conf.c src/conf/virchrdev.c src/conf/virdomainobjlist.c +src/conf/virnodedeviceobj.c src/conf/virsecretobj.c src/cpu/cpu.c src/cpu/cpu_arm.c diff --git a/src/Makefile.am b/src/Makefile.am index a85cd0df8a..7d42eac315 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -390,7 +390,8 @@ SECRET_CONF_SOURCES = \ # Network driver generic impl APIs NODE_DEVICE_CONF_SOURCES = \ - conf/node_device_conf.c conf/node_device_conf.h + conf/node_device_conf.c conf/node_device_conf.h \ + conf/virnodedeviceobj.c conf/virnodedeviceobj.h CPU_CONF_SOURCES = \ conf/cpu_conf.c conf/cpu_conf.h diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c index 43e23fc0c1..bc365276ba 100644 --- a/src/conf/node_device_conf.c +++ b/src/conf/node_device_conf.c @@ -85,170 +85,6 @@ virNodeDevCapsDefParseString(const char *xpath, return 0; } -int virNodeDeviceHasCap(const virNodeDeviceObj *dev, const char *cap) -{ - virNodeDevCapsDefPtr caps = dev->def->caps; - const char *fc_host_cap = - virNodeDevCapTypeToString(VIR_NODE_DEV_CAP_FC_HOST); - const char *vports_cap = - virNodeDevCapTypeToString(VIR_NODE_DEV_CAP_VPORTS); - - while (caps) { - if (STREQ(cap, virNodeDevCapTypeToString(caps->data.type))) - return 1; - else if (caps->data.type == VIR_NODE_DEV_CAP_SCSI_HOST) - if ((STREQ(cap, fc_host_cap) && - (caps->data.scsi_host.flags & - VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST)) || - (STREQ(cap, vports_cap) && - (caps->data.scsi_host.flags & - VIR_NODE_DEV_CAP_FLAG_HBA_VPORT_OPS))) - return 1; - caps = caps->next; - } - return 0; -} - - -/* virNodeDeviceFindFCCapDef: - * @dev: Pointer to current device - * - * Search the device object 'caps' array for fc_host capability. - * - * Returns: - * Pointer to the caps or NULL if not found - */ -static virNodeDevCapsDefPtr -virNodeDeviceFindFCCapDef(const virNodeDeviceObj *dev) -{ - virNodeDevCapsDefPtr caps = dev->def->caps; - - while (caps) { - if (caps->data.type == VIR_NODE_DEV_CAP_SCSI_HOST && - (caps->data.scsi_host.flags & VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST)) - break; - - caps = caps->next; - } - return caps; -} - - -/* virNodeDeviceFindVPORTCapDef: - * @dev: Pointer to current device - * - * Search the device object 'caps' array for vport_ops capability. - * - * Returns: - * Pointer to the caps or NULL if not found - */ -static virNodeDevCapsDefPtr -virNodeDeviceFindVPORTCapDef(const virNodeDeviceObj *dev) -{ - virNodeDevCapsDefPtr caps = dev->def->caps; - - while (caps) { - if (caps->data.type == VIR_NODE_DEV_CAP_SCSI_HOST && - (caps->data.scsi_host.flags & VIR_NODE_DEV_CAP_FLAG_HBA_VPORT_OPS)) - break; - - caps = caps->next; - } - return caps; -} - - -virNodeDeviceObjPtr -virNodeDeviceFindBySysfsPath(virNodeDeviceObjListPtr devs, - const char *sysfs_path) -{ - size_t i; - - for (i = 0; i < devs->count; i++) { - virNodeDeviceObjLock(devs->objs[i]); - if ((devs->objs[i]->def->sysfs_path != NULL) && - (STREQ(devs->objs[i]->def->sysfs_path, sysfs_path))) { - return devs->objs[i]; - } - virNodeDeviceObjUnlock(devs->objs[i]); - } - - return NULL; -} - - -virNodeDeviceObjPtr virNodeDeviceFindByName(virNodeDeviceObjListPtr devs, - const char *name) -{ - size_t i; - - for (i = 0; i < devs->count; i++) { - virNodeDeviceObjLock(devs->objs[i]); - if (STREQ(devs->objs[i]->def->name, name)) - return devs->objs[i]; - virNodeDeviceObjUnlock(devs->objs[i]); - } - - return NULL; -} - - -static virNodeDeviceObjPtr -virNodeDeviceFindByWWNs(virNodeDeviceObjListPtr devs, - const char *parent_wwnn, - const char *parent_wwpn) -{ - size_t i; - - for (i = 0; i < devs->count; i++) { - virNodeDevCapsDefPtr cap; - virNodeDeviceObjLock(devs->objs[i]); - if ((cap = virNodeDeviceFindFCCapDef(devs->objs[i])) && - STREQ_NULLABLE(cap->data.scsi_host.wwnn, parent_wwnn) && - STREQ_NULLABLE(cap->data.scsi_host.wwpn, parent_wwpn)) - return devs->objs[i]; - virNodeDeviceObjUnlock(devs->objs[i]); - } - - return NULL; -} - - -static virNodeDeviceObjPtr -virNodeDeviceFindByFabricWWN(virNodeDeviceObjListPtr devs, - const char *parent_fabric_wwn) -{ - size_t i; - - for (i = 0; i < devs->count; i++) { - virNodeDevCapsDefPtr cap; - virNodeDeviceObjLock(devs->objs[i]); - if ((cap = virNodeDeviceFindFCCapDef(devs->objs[i])) && - STREQ_NULLABLE(cap->data.scsi_host.fabric_wwn, parent_fabric_wwn)) - return devs->objs[i]; - virNodeDeviceObjUnlock(devs->objs[i]); - } - - return NULL; -} - - -static virNodeDeviceObjPtr -virNodeDeviceFindByCap(virNodeDeviceObjListPtr devs, - const char *cap) -{ - size_t i; - - for (i = 0; i < devs->count; i++) { - virNodeDeviceObjLock(devs->objs[i]); - if (virNodeDeviceHasCap(devs->objs[i], cap)) - return devs->objs[i]; - virNodeDeviceObjUnlock(devs->objs[i]); - } - - return NULL; -} - void virNodeDeviceDefFree(virNodeDeviceDefPtr def) { @@ -278,82 +114,6 @@ void virNodeDeviceDefFree(virNodeDeviceDefPtr def) VIR_FREE(def); } -void virNodeDeviceObjFree(virNodeDeviceObjPtr dev) -{ - if (!dev) - return; - - virNodeDeviceDefFree(dev->def); - if (dev->privateFree) - (*dev->privateFree)(dev->privateData); - - virMutexDestroy(&dev->lock); - - VIR_FREE(dev); -} - -void virNodeDeviceObjListFree(virNodeDeviceObjListPtr devs) -{ - size_t i; - for (i = 0; i < devs->count; i++) - virNodeDeviceObjFree(devs->objs[i]); - VIR_FREE(devs->objs); - devs->count = 0; -} - -virNodeDeviceObjPtr virNodeDeviceAssignDef(virNodeDeviceObjListPtr devs, - virNodeDeviceDefPtr def) -{ - virNodeDeviceObjPtr device; - - if ((device = virNodeDeviceFindByName(devs, def->name))) { - virNodeDeviceDefFree(device->def); - device->def = def; - return device; - } - - if (VIR_ALLOC(device) < 0) - return NULL; - - if (virMutexInit(&device->lock) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("cannot initialize mutex")); - VIR_FREE(device); - return NULL; - } - virNodeDeviceObjLock(device); - - if (VIR_APPEND_ELEMENT_COPY(devs->objs, devs->count, device) < 0) { - virNodeDeviceObjUnlock(device); - virNodeDeviceObjFree(device); - return NULL; - } - device->def = def; - - return device; - -} - -void virNodeDeviceObjRemove(virNodeDeviceObjListPtr devs, - virNodeDeviceObjPtr *dev) -{ - size_t i; - - virNodeDeviceObjUnlock(*dev); - - for (i = 0; i < devs->count; i++) { - virNodeDeviceObjLock(*dev); - if (devs->objs[i] == *dev) { - virNodeDeviceObjUnlock(*dev); - virNodeDeviceObjFree(devs->objs[i]); - *dev = NULL; - - VIR_DELETE_ELEMENT(devs->objs, i, devs->count); - break; - } - virNodeDeviceObjUnlock(*dev); - } -} static void virPCIELinkFormat(virBufferPtr buf, @@ -1976,152 +1736,6 @@ virNodeDeviceGetWWNs(virNodeDeviceDefPtr def, return ret; } -/* - * Return the NPIV dev's parent device name - */ -/* virNodeDeviceFindFCParentHost: - * @parent: Pointer to node device object - * - * Search the capabilities for the device to find the FC capabilities - * in order to set the parent_host value. - * - * Returns: - * parent_host value on success (>= 0), -1 otherwise. - */ -static int -virNodeDeviceFindFCParentHost(virNodeDeviceObjPtr parent) -{ - virNodeDevCapsDefPtr cap = virNodeDeviceFindVPORTCapDef(parent); - - if (!cap) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Parent device %s is not capable " - "of vport operations"), - parent->def->name); - return -1; - } - - return cap->data.scsi_host.host; -} - - -static int -virNodeDeviceGetParentHostByParent(virNodeDeviceObjListPtr devs, - const char *dev_name, - const char *parent_name) -{ - virNodeDeviceObjPtr parent = NULL; - int ret; - - if (!(parent = virNodeDeviceFindByName(devs, parent_name))) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Could not find parent device for '%s'"), - dev_name); - return -1; - } - - ret = virNodeDeviceFindFCParentHost(parent); - - virNodeDeviceObjUnlock(parent); - - return ret; -} - - -static int -virNodeDeviceGetParentHostByWWNs(virNodeDeviceObjListPtr devs, - const char *dev_name, - const char *parent_wwnn, - const char *parent_wwpn) -{ - virNodeDeviceObjPtr parent = NULL; - int ret; - - if (!(parent = virNodeDeviceFindByWWNs(devs, parent_wwnn, parent_wwpn))) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Could not find parent device for '%s'"), - dev_name); - return -1; - } - - ret = virNodeDeviceFindFCParentHost(parent); - - virNodeDeviceObjUnlock(parent); - - return ret; -} - - -static int -virNodeDeviceGetParentHostByFabricWWN(virNodeDeviceObjListPtr devs, - const char *dev_name, - const char *parent_fabric_wwn) -{ - virNodeDeviceObjPtr parent = NULL; - int ret; - - if (!(parent = virNodeDeviceFindByFabricWWN(devs, parent_fabric_wwn))) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Could not find parent device for '%s'"), - dev_name); - return -1; - } - - ret = virNodeDeviceFindFCParentHost(parent); - - virNodeDeviceObjUnlock(parent); - - return ret; -} - - -static int -virNodeDeviceFindVportParentHost(virNodeDeviceObjListPtr devs) -{ - virNodeDeviceObjPtr parent = NULL; - const char *cap = virNodeDevCapTypeToString(VIR_NODE_DEV_CAP_VPORTS); - int ret; - - if (!(parent = virNodeDeviceFindByCap(devs, cap))) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Could not find any vport capable device")); - return -1; - } - - ret = virNodeDeviceFindFCParentHost(parent); - - virNodeDeviceObjUnlock(parent); - - return ret; -} - - -int -virNodeDeviceGetParentHost(virNodeDeviceObjListPtr devs, - virNodeDeviceDefPtr def, - int create) -{ - int parent_host = -1; - - if (def->parent) { - parent_host = virNodeDeviceGetParentHostByParent(devs, def->name, - def->parent); - } else if (def->parent_wwnn && def->parent_wwpn) { - parent_host = virNodeDeviceGetParentHostByWWNs(devs, def->name, - def->parent_wwnn, - def->parent_wwpn); - } else if (def->parent_fabric_wwn) { - parent_host = - virNodeDeviceGetParentHostByFabricWWN(devs, def->name, - def->parent_fabric_wwn); - } else if (create == CREATE_DEVICE) { - /* Try to find a vport capable scsi_host when no parent supplied */ - parent_host = virNodeDeviceFindVportParentHost(devs); - } - - return parent_host; -} - void virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps) { @@ -2198,125 +1812,6 @@ void virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps) } -void virNodeDeviceObjLock(virNodeDeviceObjPtr obj) -{ - virMutexLock(&obj->lock); -} - -void virNodeDeviceObjUnlock(virNodeDeviceObjPtr obj) -{ - virMutexUnlock(&obj->lock); -} - -static bool -virNodeDeviceCapMatch(virNodeDeviceObjPtr devobj, - int type) -{ - virNodeDevCapsDefPtr cap = NULL; - - for (cap = devobj->def->caps; cap; cap = cap->next) { - if (type == cap->data.type) - return true; - - if (cap->data.type == VIR_NODE_DEV_CAP_SCSI_HOST) { - if (type == VIR_NODE_DEV_CAP_FC_HOST && - (cap->data.scsi_host.flags & - VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST)) - return true; - - if (type == VIR_NODE_DEV_CAP_VPORTS && - (cap->data.scsi_host.flags & - VIR_NODE_DEV_CAP_FLAG_HBA_VPORT_OPS)) - return true; - } - } - - return false; -} - -#define MATCH(FLAG) ((flags & (VIR_CONNECT_LIST_NODE_DEVICES_CAP_ ## FLAG)) && \ - virNodeDeviceCapMatch(devobj, VIR_NODE_DEV_CAP_ ## FLAG)) -static bool -virNodeDeviceMatch(virNodeDeviceObjPtr devobj, - unsigned int flags) -{ - /* filter by cap type */ - if (flags & VIR_CONNECT_LIST_NODE_DEVICES_FILTERS_CAP) { - if (!(MATCH(SYSTEM) || - MATCH(PCI_DEV) || - MATCH(USB_DEV) || - MATCH(USB_INTERFACE) || - MATCH(NET) || - MATCH(SCSI_HOST) || - MATCH(SCSI_TARGET) || - MATCH(SCSI) || - MATCH(STORAGE) || - MATCH(FC_HOST) || - MATCH(VPORTS) || - MATCH(SCSI_GENERIC) || - MATCH(DRM))) - return false; - } - - return true; -} -#undef MATCH - -int -virNodeDeviceObjListExport(virConnectPtr conn, - virNodeDeviceObjList devobjs, - virNodeDevicePtr **devices, - virNodeDeviceObjListFilter filter, - unsigned int flags) -{ - virNodeDevicePtr *tmp_devices = NULL; - virNodeDevicePtr device = NULL; - int ndevices = 0; - int ret = -1; - size_t i; - - if (devices && VIR_ALLOC_N(tmp_devices, devobjs.count + 1) < 0) - goto cleanup; - - for (i = 0; i < devobjs.count; i++) { - virNodeDeviceObjPtr devobj = devobjs.objs[i]; - virNodeDeviceObjLock(devobj); - if ((!filter || filter(conn, devobj->def)) && - virNodeDeviceMatch(devobj, flags)) { - if (devices) { - if (!(device = virGetNodeDevice(conn, devobj->def->name)) || - VIR_STRDUP(device->parent, devobj->def->parent) < 0) { - virObjectUnref(device); - virNodeDeviceObjUnlock(devobj); - goto cleanup; - } - tmp_devices[ndevices] = device; - } - ndevices++; - } - virNodeDeviceObjUnlock(devobj); - } - - if (tmp_devices) { - /* trim the array to the final size */ - ignore_value(VIR_REALLOC_N(tmp_devices, ndevices + 1)); - *devices = tmp_devices; - tmp_devices = NULL; - } - - ret = ndevices; - - cleanup: - if (tmp_devices) { - for (i = 0; i < ndevices; i++) - virObjectUnref(tmp_devices[i]); - } - - VIR_FREE(tmp_devices); - return ret; -} - - /* virNodeDeviceGetParentName * @conn: Connection pointer * @nodedev_name: Node device to lookup diff --git a/src/conf/node_device_conf.h b/src/conf/node_device_conf.h index 8213c27a1d..6c94262750 100644 --- a/src/conf/node_device_conf.h +++ b/src/conf/node_device_conf.h @@ -28,10 +28,8 @@ # include "internal.h" # include "virbitmap.h" # include "virutil.h" -# include "virthread.h" # include "virpci.h" # include "device_conf.h" -# include "object_event.h" # include @@ -253,34 +251,6 @@ struct _virNodeDeviceObjList { virNodeDeviceObjPtr *objs; }; -typedef struct _virNodeDeviceDriverState virNodeDeviceDriverState; -typedef virNodeDeviceDriverState *virNodeDeviceDriverStatePtr; -struct _virNodeDeviceDriverState { - virMutex lock; - - virNodeDeviceObjList devs; /* currently-known devices */ - void *privateData; /* driver-specific private data */ - - /* Immutable pointer, self-locking APIs */ - virObjectEventStatePtr nodeDeviceEventState; -}; - - -int virNodeDeviceHasCap(const virNodeDeviceObj *dev, const char *cap); - -virNodeDeviceObjPtr virNodeDeviceFindByName(virNodeDeviceObjListPtr devs, - const char *name); -virNodeDeviceObjPtr -virNodeDeviceFindBySysfsPath(virNodeDeviceObjListPtr devs, - const char *sysfs_path) - ATTRIBUTE_NONNULL(2); - -virNodeDeviceObjPtr virNodeDeviceAssignDef(virNodeDeviceObjListPtr devs, - virNodeDeviceDefPtr def); - -void virNodeDeviceObjRemove(virNodeDeviceObjListPtr devs, - virNodeDeviceObjPtr *dev); - char *virNodeDeviceDefFormat(const virNodeDeviceDef *def); virNodeDeviceDefPtr virNodeDeviceDefParseString(const char *str, @@ -298,21 +268,10 @@ int virNodeDeviceGetWWNs(virNodeDeviceDefPtr def, char **wwnn, char **wwpn); -int virNodeDeviceGetParentHost(virNodeDeviceObjListPtr devs, - virNodeDeviceDefPtr def, - int create); - void virNodeDeviceDefFree(virNodeDeviceDefPtr def); -void virNodeDeviceObjFree(virNodeDeviceObjPtr dev); - -void virNodeDeviceObjListFree(virNodeDeviceObjListPtr devs); - void virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps); -void virNodeDeviceObjLock(virNodeDeviceObjPtr obj); -void virNodeDeviceObjUnlock(virNodeDeviceObjPtr obj); - # define VIR_CONNECT_LIST_NODE_DEVICES_FILTERS_CAP \ (VIR_CONNECT_LIST_NODE_DEVICES_CAP_SYSTEM | \ VIR_CONNECT_LIST_NODE_DEVICES_CAP_PCI_DEV | \ @@ -328,15 +287,6 @@ void virNodeDeviceObjUnlock(virNodeDeviceObjPtr obj); VIR_CONNECT_LIST_NODE_DEVICES_CAP_SCSI_GENERIC | \ VIR_CONNECT_LIST_NODE_DEVICES_CAP_DRM) -typedef bool (*virNodeDeviceObjListFilter)(virConnectPtr conn, - virNodeDeviceDefPtr def); - -int virNodeDeviceObjListExport(virConnectPtr conn, - virNodeDeviceObjList devobjs, - virNodeDevicePtr **devices, - virNodeDeviceObjListFilter filter, - unsigned int flags); - char *virNodeDeviceGetParentName(virConnectPtr conn, const char *nodedev_name); diff --git a/src/conf/virnodedeviceobj.c b/src/conf/virnodedeviceobj.c new file mode 100644 index 0000000000..83f7217364 --- /dev/null +++ b/src/conf/virnodedeviceobj.c @@ -0,0 +1,542 @@ +/* + * virnodedeviceobj.c: node device object handling + * (derived from node_device_conf.c) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + */ + +#include + +#include "datatypes.h" +#include "node_device_conf.h" + +#include "viralloc.h" +#include "virnodedeviceobj.h" +#include "virerror.h" +#include "virlog.h" +#include "virstring.h" + +#define VIR_FROM_THIS VIR_FROM_NODEDEV + +VIR_LOG_INIT("conf.virnodedeviceobj"); + + +int virNodeDeviceHasCap(const virNodeDeviceObj *dev, const char *cap) +{ + virNodeDevCapsDefPtr caps = dev->def->caps; + const char *fc_host_cap = + virNodeDevCapTypeToString(VIR_NODE_DEV_CAP_FC_HOST); + const char *vports_cap = + virNodeDevCapTypeToString(VIR_NODE_DEV_CAP_VPORTS); + + while (caps) { + if (STREQ(cap, virNodeDevCapTypeToString(caps->data.type))) + return 1; + else if (caps->data.type == VIR_NODE_DEV_CAP_SCSI_HOST) + if ((STREQ(cap, fc_host_cap) && + (caps->data.scsi_host.flags & + VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST)) || + (STREQ(cap, vports_cap) && + (caps->data.scsi_host.flags & + VIR_NODE_DEV_CAP_FLAG_HBA_VPORT_OPS))) + return 1; + caps = caps->next; + } + return 0; +} + + +/* virNodeDeviceFindFCCapDef: + * @dev: Pointer to current device + * + * Search the device object 'caps' array for fc_host capability. + * + * Returns: + * Pointer to the caps or NULL if not found + */ +static virNodeDevCapsDefPtr +virNodeDeviceFindFCCapDef(const virNodeDeviceObj *dev) +{ + virNodeDevCapsDefPtr caps = dev->def->caps; + + while (caps) { + if (caps->data.type == VIR_NODE_DEV_CAP_SCSI_HOST && + (caps->data.scsi_host.flags & VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST)) + break; + + caps = caps->next; + } + return caps; +} + + +/* virNodeDeviceFindVPORTCapDef: + * @dev: Pointer to current device + * + * Search the device object 'caps' array for vport_ops capability. + * + * Returns: + * Pointer to the caps or NULL if not found + */ +static virNodeDevCapsDefPtr +virNodeDeviceFindVPORTCapDef(const virNodeDeviceObj *dev) +{ + virNodeDevCapsDefPtr caps = dev->def->caps; + + while (caps) { + if (caps->data.type == VIR_NODE_DEV_CAP_SCSI_HOST && + (caps->data.scsi_host.flags & VIR_NODE_DEV_CAP_FLAG_HBA_VPORT_OPS)) + break; + + caps = caps->next; + } + return caps; +} + + +virNodeDeviceObjPtr +virNodeDeviceFindBySysfsPath(virNodeDeviceObjListPtr devs, + const char *sysfs_path) +{ + size_t i; + + for (i = 0; i < devs->count; i++) { + virNodeDeviceObjLock(devs->objs[i]); + if ((devs->objs[i]->def->sysfs_path != NULL) && + (STREQ(devs->objs[i]->def->sysfs_path, sysfs_path))) { + return devs->objs[i]; + } + virNodeDeviceObjUnlock(devs->objs[i]); + } + + return NULL; +} + + +virNodeDeviceObjPtr virNodeDeviceFindByName(virNodeDeviceObjListPtr devs, + const char *name) +{ + size_t i; + + for (i = 0; i < devs->count; i++) { + virNodeDeviceObjLock(devs->objs[i]); + if (STREQ(devs->objs[i]->def->name, name)) + return devs->objs[i]; + virNodeDeviceObjUnlock(devs->objs[i]); + } + + return NULL; +} + + +static virNodeDeviceObjPtr +virNodeDeviceFindByWWNs(virNodeDeviceObjListPtr devs, + const char *parent_wwnn, + const char *parent_wwpn) +{ + size_t i; + + for (i = 0; i < devs->count; i++) { + virNodeDevCapsDefPtr cap; + virNodeDeviceObjLock(devs->objs[i]); + if ((cap = virNodeDeviceFindFCCapDef(devs->objs[i])) && + STREQ_NULLABLE(cap->data.scsi_host.wwnn, parent_wwnn) && + STREQ_NULLABLE(cap->data.scsi_host.wwpn, parent_wwpn)) + return devs->objs[i]; + virNodeDeviceObjUnlock(devs->objs[i]); + } + + return NULL; +} + + +static virNodeDeviceObjPtr +virNodeDeviceFindByFabricWWN(virNodeDeviceObjListPtr devs, + const char *parent_fabric_wwn) +{ + size_t i; + + for (i = 0; i < devs->count; i++) { + virNodeDevCapsDefPtr cap; + virNodeDeviceObjLock(devs->objs[i]); + if ((cap = virNodeDeviceFindFCCapDef(devs->objs[i])) && + STREQ_NULLABLE(cap->data.scsi_host.fabric_wwn, parent_fabric_wwn)) + return devs->objs[i]; + virNodeDeviceObjUnlock(devs->objs[i]); + } + + return NULL; +} + + +static virNodeDeviceObjPtr +virNodeDeviceFindByCap(virNodeDeviceObjListPtr devs, + const char *cap) +{ + size_t i; + + for (i = 0; i < devs->count; i++) { + virNodeDeviceObjLock(devs->objs[i]); + if (virNodeDeviceHasCap(devs->objs[i], cap)) + return devs->objs[i]; + virNodeDeviceObjUnlock(devs->objs[i]); + } + + return NULL; +} + + +void virNodeDeviceObjFree(virNodeDeviceObjPtr dev) +{ + if (!dev) + return; + + virNodeDeviceDefFree(dev->def); + if (dev->privateFree) + (*dev->privateFree)(dev->privateData); + + virMutexDestroy(&dev->lock); + + VIR_FREE(dev); +} + +void virNodeDeviceObjListFree(virNodeDeviceObjListPtr devs) +{ + size_t i; + for (i = 0; i < devs->count; i++) + virNodeDeviceObjFree(devs->objs[i]); + VIR_FREE(devs->objs); + devs->count = 0; +} + +virNodeDeviceObjPtr virNodeDeviceAssignDef(virNodeDeviceObjListPtr devs, + virNodeDeviceDefPtr def) +{ + virNodeDeviceObjPtr device; + + if ((device = virNodeDeviceFindByName(devs, def->name))) { + virNodeDeviceDefFree(device->def); + device->def = def; + return device; + } + + if (VIR_ALLOC(device) < 0) + return NULL; + + if (virMutexInit(&device->lock) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("cannot initialize mutex")); + VIR_FREE(device); + return NULL; + } + virNodeDeviceObjLock(device); + + if (VIR_APPEND_ELEMENT_COPY(devs->objs, devs->count, device) < 0) { + virNodeDeviceObjUnlock(device); + virNodeDeviceObjFree(device); + return NULL; + } + device->def = def; + + return device; + +} + +void virNodeDeviceObjRemove(virNodeDeviceObjListPtr devs, + virNodeDeviceObjPtr *dev) +{ + size_t i; + + virNodeDeviceObjUnlock(*dev); + + for (i = 0; i < devs->count; i++) { + virNodeDeviceObjLock(*dev); + if (devs->objs[i] == *dev) { + virNodeDeviceObjUnlock(*dev); + virNodeDeviceObjFree(devs->objs[i]); + *dev = NULL; + + VIR_DELETE_ELEMENT(devs->objs, i, devs->count); + break; + } + virNodeDeviceObjUnlock(*dev); + } +} + + +/* + * Return the NPIV dev's parent device name + */ +/* virNodeDeviceFindFCParentHost: + * @parent: Pointer to node device object + * + * Search the capabilities for the device to find the FC capabilities + * in order to set the parent_host value. + * + * Returns: + * parent_host value on success (>= 0), -1 otherwise. + */ +static int +virNodeDeviceFindFCParentHost(virNodeDeviceObjPtr parent) +{ + virNodeDevCapsDefPtr cap = virNodeDeviceFindVPORTCapDef(parent); + + if (!cap) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Parent device %s is not capable " + "of vport operations"), + parent->def->name); + return -1; + } + + return cap->data.scsi_host.host; +} + + +static int +virNodeDeviceGetParentHostByParent(virNodeDeviceObjListPtr devs, + const char *dev_name, + const char *parent_name) +{ + virNodeDeviceObjPtr parent = NULL; + int ret; + + if (!(parent = virNodeDeviceFindByName(devs, parent_name))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not find parent device for '%s'"), + dev_name); + return -1; + } + + ret = virNodeDeviceFindFCParentHost(parent); + + virNodeDeviceObjUnlock(parent); + + return ret; +} + + +static int +virNodeDeviceGetParentHostByWWNs(virNodeDeviceObjListPtr devs, + const char *dev_name, + const char *parent_wwnn, + const char *parent_wwpn) +{ + virNodeDeviceObjPtr parent = NULL; + int ret; + + if (!(parent = virNodeDeviceFindByWWNs(devs, parent_wwnn, parent_wwpn))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not find parent device for '%s'"), + dev_name); + return -1; + } + + ret = virNodeDeviceFindFCParentHost(parent); + + virNodeDeviceObjUnlock(parent); + + return ret; +} + + +static int +virNodeDeviceGetParentHostByFabricWWN(virNodeDeviceObjListPtr devs, + const char *dev_name, + const char *parent_fabric_wwn) +{ + virNodeDeviceObjPtr parent = NULL; + int ret; + + if (!(parent = virNodeDeviceFindByFabricWWN(devs, parent_fabric_wwn))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not find parent device for '%s'"), + dev_name); + return -1; + } + + ret = virNodeDeviceFindFCParentHost(parent); + + virNodeDeviceObjUnlock(parent); + + return ret; +} + + +static int +virNodeDeviceFindVportParentHost(virNodeDeviceObjListPtr devs) +{ + virNodeDeviceObjPtr parent = NULL; + const char *cap = virNodeDevCapTypeToString(VIR_NODE_DEV_CAP_VPORTS); + int ret; + + if (!(parent = virNodeDeviceFindByCap(devs, cap))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not find any vport capable device")); + return -1; + } + + ret = virNodeDeviceFindFCParentHost(parent); + + virNodeDeviceObjUnlock(parent); + + return ret; +} + + +int +virNodeDeviceGetParentHost(virNodeDeviceObjListPtr devs, + virNodeDeviceDefPtr def, + int create) +{ + int parent_host = -1; + + if (def->parent) { + parent_host = virNodeDeviceGetParentHostByParent(devs, def->name, + def->parent); + } else if (def->parent_wwnn && def->parent_wwpn) { + parent_host = virNodeDeviceGetParentHostByWWNs(devs, def->name, + def->parent_wwnn, + def->parent_wwpn); + } else if (def->parent_fabric_wwn) { + parent_host = + virNodeDeviceGetParentHostByFabricWWN(devs, def->name, + def->parent_fabric_wwn); + } else if (create == CREATE_DEVICE) { + /* Try to find a vport capable scsi_host when no parent supplied */ + parent_host = virNodeDeviceFindVportParentHost(devs); + } + + return parent_host; +} + + +void virNodeDeviceObjLock(virNodeDeviceObjPtr obj) +{ + virMutexLock(&obj->lock); +} + +void virNodeDeviceObjUnlock(virNodeDeviceObjPtr obj) +{ + virMutexUnlock(&obj->lock); +} + +static bool +virNodeDeviceCapMatch(virNodeDeviceObjPtr devobj, + int type) +{ + virNodeDevCapsDefPtr cap = NULL; + + for (cap = devobj->def->caps; cap; cap = cap->next) { + if (type == cap->data.type) + return true; + + if (cap->data.type == VIR_NODE_DEV_CAP_SCSI_HOST) { + if (type == VIR_NODE_DEV_CAP_FC_HOST && + (cap->data.scsi_host.flags & + VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST)) + return true; + + if (type == VIR_NODE_DEV_CAP_VPORTS && + (cap->data.scsi_host.flags & + VIR_NODE_DEV_CAP_FLAG_HBA_VPORT_OPS)) + return true; + } + } + + return false; +} + +#define MATCH(FLAG) ((flags & (VIR_CONNECT_LIST_NODE_DEVICES_CAP_ ## FLAG)) && \ + virNodeDeviceCapMatch(devobj, VIR_NODE_DEV_CAP_ ## FLAG)) +static bool +virNodeDeviceMatch(virNodeDeviceObjPtr devobj, + unsigned int flags) +{ + /* filter by cap type */ + if (flags & VIR_CONNECT_LIST_NODE_DEVICES_FILTERS_CAP) { + if (!(MATCH(SYSTEM) || + MATCH(PCI_DEV) || + MATCH(USB_DEV) || + MATCH(USB_INTERFACE) || + MATCH(NET) || + MATCH(SCSI_HOST) || + MATCH(SCSI_TARGET) || + MATCH(SCSI) || + MATCH(STORAGE) || + MATCH(FC_HOST) || + MATCH(VPORTS) || + MATCH(SCSI_GENERIC) || + MATCH(DRM))) + return false; + } + + return true; +} +#undef MATCH + +int +virNodeDeviceObjListExport(virConnectPtr conn, + virNodeDeviceObjList devobjs, + virNodeDevicePtr **devices, + virNodeDeviceObjListFilter filter, + unsigned int flags) +{ + virNodeDevicePtr *tmp_devices = NULL; + virNodeDevicePtr device = NULL; + int ndevices = 0; + int ret = -1; + size_t i; + + if (devices && VIR_ALLOC_N(tmp_devices, devobjs.count + 1) < 0) + goto cleanup; + + for (i = 0; i < devobjs.count; i++) { + virNodeDeviceObjPtr devobj = devobjs.objs[i]; + virNodeDeviceObjLock(devobj); + if ((!filter || filter(conn, devobj->def)) && + virNodeDeviceMatch(devobj, flags)) { + if (devices) { + if (!(device = virGetNodeDevice(conn, devobj->def->name)) || + VIR_STRDUP(device->parent, devobj->def->parent) < 0) { + virObjectUnref(device); + virNodeDeviceObjUnlock(devobj); + goto cleanup; + } + tmp_devices[ndevices] = device; + } + ndevices++; + } + virNodeDeviceObjUnlock(devobj); + } + + if (tmp_devices) { + /* trim the array to the final size */ + ignore_value(VIR_REALLOC_N(tmp_devices, ndevices + 1)); + *devices = tmp_devices; + tmp_devices = NULL; + } + + ret = ndevices; + + cleanup: + if (tmp_devices) { + for (i = 0; i < ndevices; i++) + virObjectUnref(tmp_devices[i]); + } + + VIR_FREE(tmp_devices); + return ret; +} diff --git a/src/conf/virnodedeviceobj.h b/src/conf/virnodedeviceobj.h new file mode 100644 index 0000000000..6ad7fb1e48 --- /dev/null +++ b/src/conf/virnodedeviceobj.h @@ -0,0 +1,78 @@ +/* + * virnodedeviceobj.h: node device object handling for node devices + * (derived from node_device_conf.h) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + */ + +#ifndef __VIRNODEDEVICEOBJ_H__ +# define __VIRNODEDEVICEOBJ_H__ + +# include "internal.h" +# include "virthread.h" + +# include "node_device_conf.h" +# include "object_event.h" + + +typedef struct _virNodeDeviceDriverState virNodeDeviceDriverState; +typedef virNodeDeviceDriverState *virNodeDeviceDriverStatePtr; +struct _virNodeDeviceDriverState { + virMutex lock; + + virNodeDeviceObjList devs; /* currently-known devices */ + void *privateData; /* driver-specific private data */ + + /* Immutable pointer, self-locking APIs */ + virObjectEventStatePtr nodeDeviceEventState; +}; + + +int virNodeDeviceHasCap(const virNodeDeviceObj *dev, const char *cap); + +virNodeDeviceObjPtr virNodeDeviceFindByName(virNodeDeviceObjListPtr devs, + const char *name); +virNodeDeviceObjPtr +virNodeDeviceFindBySysfsPath(virNodeDeviceObjListPtr devs, + const char *sysfs_path) + ATTRIBUTE_NONNULL(2); + +virNodeDeviceObjPtr virNodeDeviceAssignDef(virNodeDeviceObjListPtr devs, + virNodeDeviceDefPtr def); + +void virNodeDeviceObjRemove(virNodeDeviceObjListPtr devs, + virNodeDeviceObjPtr *dev); + +int virNodeDeviceGetParentHost(virNodeDeviceObjListPtr devs, + virNodeDeviceDefPtr def, + int create); + +void virNodeDeviceObjFree(virNodeDeviceObjPtr dev); + +void virNodeDeviceObjListFree(virNodeDeviceObjListPtr devs); + +void virNodeDeviceObjLock(virNodeDeviceObjPtr obj); +void virNodeDeviceObjUnlock(virNodeDeviceObjPtr obj); + +typedef bool (*virNodeDeviceObjListFilter)(virConnectPtr conn, + virNodeDeviceDefPtr def); + +int virNodeDeviceObjListExport(virConnectPtr conn, + virNodeDeviceObjList devobjs, + virNodeDevicePtr **devices, + virNodeDeviceObjListFilter filter, + unsigned int flags); + +#endif /* __VIRNODEDEVICEOBJ_H__ */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index bce0487ab3..8639979aeb 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -694,23 +694,13 @@ virNetDevIPRouteParseXML; virNodeDevCapsDefFree; virNodeDevCapTypeFromString; virNodeDevCapTypeToString; -virNodeDeviceAssignDef; virNodeDeviceDefFormat; virNodeDeviceDefFree; virNodeDeviceDefParseFile; virNodeDeviceDefParseNode; virNodeDeviceDefParseString; -virNodeDeviceFindByName; -virNodeDeviceFindBySysfsPath; -virNodeDeviceGetParentHost; virNodeDeviceGetParentName; virNodeDeviceGetWWNs; -virNodeDeviceHasCap; -virNodeDeviceObjListExport; -virNodeDeviceObjListFree; -virNodeDeviceObjLock; -virNodeDeviceObjRemove; -virNodeDeviceObjUnlock; # conf/node_device_event.h @@ -958,6 +948,19 @@ virDomainObjListRemoveLocked; virDomainObjListRename; +# conf/virnodedeviceobj.h +virNodeDeviceAssignDef; +virNodeDeviceFindByName; +virNodeDeviceFindBySysfsPath; +virNodeDeviceGetParentHost; +virNodeDeviceHasCap; +virNodeDeviceObjListExport; +virNodeDeviceObjListFree; +virNodeDeviceObjLock; +virNodeDeviceObjRemove; +virNodeDeviceObjUnlock; + + # conf/virsecretobj.h virSecretLoadAllConfigs; virSecretObjDeleteConfig; diff --git a/src/node_device/node_device_driver.h b/src/node_device/node_device_driver.h index 56f89ab03a..bc8af8a9e7 100644 --- a/src/node_device/node_device_driver.h +++ b/src/node_device/node_device_driver.h @@ -26,7 +26,7 @@ # include "internal.h" # include "driver.h" -# include "node_device_conf.h" +# include "virnodedeviceobj.h" # define LINUX_NEW_DEVICE_WAIT_TIME 60 diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 314f08cce1..c6214c62f3 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -51,6 +51,7 @@ #include "storage_conf.h" #include "storage_event.h" #include "node_device_conf.h" +#include "virnodedeviceobj.h" #include "node_device_event.h" #include "virxml.h" #include "virthread.h"