[libvirt] [PATCH 1/3] conf: Introduce virnodedeviceobj

John Ferlan jferlan at redhat.com
Thu Mar 2 00:27:14 UTC 2017


Move all the NodeDeviceObj API's into their own module virnodedeviceobj
from the node_device_conf

Purely code motion at this point, plus adjustments to cleanly build.

Signed-off-by: John Ferlan <jferlan at redhat.com>
---
 po/POTFILES.in                       |   1 +
 src/Makefile.am                      |   3 +-
 src/conf/node_device_conf.c          | 505 --------------------------------
 src/conf/node_device_conf.h          |  50 ----
 src/conf/virnodedeviceobj.c          | 542 +++++++++++++++++++++++++++++++++++
 src/conf/virnodedeviceobj.h          |  78 +++++
 src/libvirt_private.syms             |  23 +-
 src/node_device/node_device_driver.h |   2 +-
 src/test/test_driver.c               |   1 +
 9 files changed, 638 insertions(+), 567 deletions(-)
 create mode 100644 src/conf/virnodedeviceobj.c
 create mode 100644 src/conf/virnodedeviceobj.h

diff --git a/po/POTFILES.in b/po/POTFILES.in
index 9f66697..7c7f530 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 a85cd0d..7d42eac 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 43e23fc..bc36527 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 8213c27..6c94262 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 <libxml/tree.h>
 
@@ -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 0000000..83f7217
--- /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
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#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 0000000..6ad7fb1
--- /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
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#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 bce0487..8639979 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 56f89ab..bc8af8a 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 314f08c..c6214c6 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"
-- 
2.9.3




More information about the libvir-list mailing list