[libvirt] [PATCH RFC 3/9] nodedev: Convert virNodeDevObj[List] to use virPoolObj[Table]

John Ferlan jferlan at redhat.com
Sat Feb 11 16:29:39 UTC 2017


Use the virPoolObj[Table] object management model in order to manage the
Node Device objects.

While making the adjustments to use the new model, there are some code
formatting adjustments that were also made with the goal to follow more
recent code flow and layout.

For API's that were static, rather than use "virNode*", some names were
converted to be "node*" - makes it easier to determine while reading code
what is local and what is "outside" the perveyance of the module.

For the node_device_hal.c - removed the usage of privateData - it wasn't
actually used anyway other than alloc()/free().  The NODE_DEV_UDI was never
referenced.

Signed-off-by: John Ferlan <jferlan at redhat.com>
---
 po/POTFILES.in                       |   1 +
 src/Makefile.am                      |   3 +-
 src/conf/node_device_conf.c          | 497 +-----------------------------
 src/conf/node_device_conf.h          |  85 +-----
 src/conf/virnodedeviceobj.c          | 570 +++++++++++++++++++++++++++++++++++
 src/conf/virnodedeviceobj.h          |  86 ++++++
 src/libvirt_private.syms             |  25 +-
 src/node_device/node_device_driver.c | 388 ++++++++++--------------
 src/node_device/node_device_driver.h |   2 +-
 src/node_device/node_device_hal.c    |  82 ++---
 src/node_device/node_device_udev.c   |  76 +++--
 src/test/test_driver.c               | 294 +++++++-----------
 12 files changed, 1032 insertions(+), 1077 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 95fa9a6..37379b5 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/virpoolobj.c
 src/conf/virsecretobj.c
 src/cpu/cpu.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 03a8cf3..20ee73a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -392,7 +392,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 4d3268f..cfd576d 100644
--- a/src/conf/node_device_conf.c
+++ b/src/conf/node_device_conf.c
@@ -59,7 +59,7 @@ VIR_ENUM_IMPL(virNodeDevNetCap, VIR_NODE_DEV_CAP_NET_LAST,
               "80211")
 
 static int
-virNodeDevCapsDefParseString(const char *xpath,
+nodeDeviceCapsDefParseString(const char *xpath,
                              xmlXPathContextPtr ctxt,
                              char **string)
 {
@@ -72,173 +72,11 @@ 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)
+void
+virNodeDeviceDefFree(void *opaque)
 {
+    virNodeDeviceDefPtr def = opaque;
     virNodeDevCapsDefPtr caps;
 
     if (!def)
@@ -263,82 +101,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,
@@ -377,7 +139,9 @@ virPCIEDeviceInfoFormat(virBufferPtr buf,
     virBufferAddLit(buf, "</pci-express>\n");
 }
 
-char *virNodeDeviceDefFormat(const virNodeDeviceDef *def)
+
+char *
+virNodeDeviceDefFormat(const virNodeDeviceDef *def)
 {
     virBuffer buf = VIR_BUFFER_INITIALIZER;
     virNodeDevCapsDefPtr caps;
@@ -1009,7 +773,7 @@ virNodeDevCapSCSIHostParseXML(xmlXPathContextPtr ctxt,
             orignode2 = ctxt->node;
             ctxt->node = nodes[i];
 
-            if (virNodeDevCapsDefParseString("string(./wwnn[1])",
+            if (nodeDeviceCapsDefParseString("string(./wwnn[1])",
                                              ctxt,
                                              &data->scsi_host.wwnn) < 0) {
                 if (virRandomGenerateWWN(&data->scsi_host.wwnn, virt_type) < 0) {
@@ -1021,7 +785,7 @@ virNodeDevCapSCSIHostParseXML(xmlXPathContextPtr ctxt,
                 }
             }
 
-            if (virNodeDevCapsDefParseString("string(./wwpn[1])",
+            if (nodeDeviceCapsDefParseString("string(./wwpn[1])",
                                              ctxt,
                                              &data->scsi_host.wwpn) < 0) {
                 if (virRandomGenerateWWN(&data->scsi_host.wwpn, virt_type) < 0) {
@@ -1872,132 +1636,6 @@ virNodeDeviceGetWWNs(virNodeDeviceDefPtr def,
     return ret;
 }
 
-/*
- * Return the NPIV dev's parent device name
- */
-/* virNodeDeviceFindFCParentHost:
- * @parent: Pointer to node device object
- * @parent_host: Pointer to return parent host number
- *
- * Search the capabilities for the device to find the FC capabilities
- * in order to set the parent_host value.
- *
- * Returns:
- *   0 on success with parent_host set, -1 otherwise;
- */
-static int
-virNodeDeviceFindFCParentHost(virNodeDeviceObjPtr parent,
-                              int *parent_host)
-{
-    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;
-    }
-
-    *parent_host = cap->data.scsi_host.host;
-    return 0;
-}
-
-
-int
-virNodeDeviceGetParentHost(virNodeDeviceObjListPtr devs,
-                           const char *dev_name,
-                           const char *parent_name,
-                           int *parent_host)
-{
-    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, parent_host);
-
-    virNodeDeviceObjUnlock(parent);
-
-    return ret;
-}
-
-
-int
-virNodeDeviceGetParentHostByWWNs(virNodeDeviceObjListPtr devs,
-                                 const char *dev_name,
-                                 const char *parent_wwnn,
-                                 const char *parent_wwpn,
-                                 int *parent_host)
-{
-    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, parent_host);
-
-    virNodeDeviceObjUnlock(parent);
-
-    return ret;
-}
-
-
-int
-virNodeDeviceGetParentHostByFabricWWN(virNodeDeviceObjListPtr devs,
-                                      const char *dev_name,
-                                      const char *parent_fabric_wwn,
-                                      int *parent_host)
-{
-    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, parent_host);
-
-    virNodeDeviceObjUnlock(parent);
-
-    return ret;
-}
-
-
-int
-virNodeDeviceFindVportParentHost(virNodeDeviceObjListPtr devs,
-                                 int *parent_host)
-{
-    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, parent_host);
-
-    virNodeDeviceObjUnlock(parent);
-
-    return ret;
-}
-
 
 void virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps)
 {
@@ -2071,120 +1709,3 @@ void virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps)
 
     VIR_FREE(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)))
-            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))) {
-                    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/node_device_conf.h b/src/conf/node_device_conf.h
index e1cdb1d..ec7f079 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>
 
@@ -207,53 +205,6 @@ struct _virNodeDeviceDef {
     virNodeDevCapsDefPtr caps;		/* optional device capabilities */
 };
 
-
-typedef struct _virNodeDeviceObj virNodeDeviceObj;
-typedef virNodeDeviceObj *virNodeDeviceObjPtr;
-struct _virNodeDeviceObj {
-    virMutex lock;
-
-    virNodeDeviceDefPtr def;		/* device definition */
-    void *privateData;			/* driver-specific private data */
-    void (*privateFree)(void *data);	/* destructor for private data */
-
-};
-
-typedef struct _virNodeDeviceObjList virNodeDeviceObjList;
-typedef virNodeDeviceObjList *virNodeDeviceObjListPtr;
-struct _virNodeDeviceObjList {
-    size_t count;
-    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,
@@ -271,36 +222,10 @@ int virNodeDeviceGetWWNs(virNodeDeviceDefPtr def,
                          char **wwnn,
                          char **wwpn);
 
-int virNodeDeviceGetParentHost(virNodeDeviceObjListPtr devs,
-                               const char *dev_name,
-                               const char *parent_name,
-                               int *parent_host);
-
-int virNodeDeviceGetParentHostByWWNs(virNodeDeviceObjListPtr devs,
-                                     const char *dev_name,
-                                     const char *parent_wwnn,
-                                     const char *parent_wwpn,
-                                     int *parent_host);
-
-int virNodeDeviceGetParentHostByFabricWWN(virNodeDeviceObjListPtr devs,
-                                          const char *dev_name,
-                                          const char *parent_fabric_wwn,
-                                          int *parent_host);
-
-int virNodeDeviceFindVportParentHost(virNodeDeviceObjListPtr devs,
-                                     int *parent_host);
-
-void virNodeDeviceDefFree(virNodeDeviceDefPtr def);
-
-void virNodeDeviceObjFree(virNodeDeviceObjPtr dev);
-
-void virNodeDeviceObjListFree(virNodeDeviceObjListPtr devs);
+void virNodeDeviceDefFree(void *opaque);
 
 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       | \
@@ -315,12 +240,4 @@ void virNodeDeviceObjUnlock(virNodeDeviceObjPtr obj);
                  VIR_CONNECT_LIST_NODE_DEVICES_CAP_VPORTS        | \
                  VIR_CONNECT_LIST_NODE_DEVICES_CAP_SCSI_GENERIC)
 
-typedef bool (*virNodeDeviceObjListFilter)(virConnectPtr conn, void *opaque);
-
-int virNodeDeviceObjListExport(virConnectPtr conn,
-                               virNodeDeviceObjList devobjs,
-                               virNodeDevicePtr **devices,
-                               virNodeDeviceObjListFilter filter,
-                               unsigned int flags);
-
 #endif /* __VIR_NODE_DEVICE_CONF_H__ */
diff --git a/src/conf/virnodedeviceobj.c b/src/conf/virnodedeviceobj.c
new file mode 100644
index 0000000..73a43ac
--- /dev/null
+++ b/src/conf/virnodedeviceobj.c
@@ -0,0 +1,570 @@
+/*
+ * 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");
+
+static int
+nodeDeviceHasCap(const virNodeDeviceDef *def,
+                 const char *cap)
+{
+    virNodeDevCapsDefPtr caps = 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;
+}
+
+
+/* nodeDeviceFindFCCapDef:
+ * @def: Node device definition
+ *
+ * Search the device object 'caps' array for fc_host capability.
+ *
+ * Returns:
+ * Pointer to the caps or NULL if not found
+ */
+static virNodeDevCapsDefPtr
+nodeDeviceFindFCCapDef(const virNodeDeviceDef *def)
+{
+    virNodeDevCapsDefPtr caps = 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;
+}
+
+
+/* nodeDeviceFindVPORTCapDef:
+ * @def: Node device definition
+ *
+ * Search the device object 'caps' array for vport_ops capability.
+ *
+ * Returns:
+ * Pointer to the caps or NULL if not found
+ */
+static virNodeDevCapsDefPtr
+nodeDeviceFindVPORTCapDef(const virNodeDeviceDef *def)
+{
+    virNodeDevCapsDefPtr caps = 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;
+}
+
+
+struct searchData {
+    const char *sysfs_path;
+    const char *cap;
+    const char *parent_wwnn;
+    const char *parent_wwpn;
+    const char *parent_fabric_wwn;
+};
+
+
+static bool
+searchBySysfsPath(virPoolObjPtr obj,
+                  void *opaque)
+{
+    virNodeDeviceDefPtr def = virPoolObjGetDef(obj);
+    struct searchData *data = opaque;
+
+    if (STREQ_NULLABLE(def->sysfs_path, data->sysfs_path))
+        return true;
+
+    return false;
+}
+
+
+static bool
+searchByCap(virPoolObjPtr obj,
+            void *opaque)
+{
+    virNodeDeviceDefPtr def = virPoolObjGetDef(obj);
+    struct searchData *data = opaque;
+
+    if (nodeDeviceHasCap(def, data->cap))
+        return true;
+
+    return false;
+}
+
+
+static bool
+searchByWWNs(virPoolObjPtr obj,
+             void *opaque)
+{
+    virNodeDeviceDefPtr def = virPoolObjGetDef(obj);
+    struct searchData *data = opaque;
+    virNodeDevCapsDefPtr cap;
+
+    if ((cap = nodeDeviceFindFCCapDef(def)) &&
+        STREQ_NULLABLE(cap->data.scsi_host.wwnn, data->parent_wwnn) &&
+        STREQ_NULLABLE(cap->data.scsi_host.wwpn, data->parent_wwpn))
+        return true;
+
+    return false;
+}
+
+
+static bool
+searchByFabricWWN(virPoolObjPtr obj,
+                  void *opaque)
+{
+    virNodeDeviceDefPtr def = virPoolObjGetDef(obj);
+    struct searchData *data = opaque;
+    virNodeDevCapsDefPtr cap;
+
+    if ((cap = nodeDeviceFindFCCapDef(def)) &&
+        STREQ_NULLABLE(cap->data.scsi_host.fabric_wwn, data->parent_fabric_wwn))
+        return true;
+
+    return false;
+}
+
+
+/* virNodeDeviceObjFindBy{SysfsPath|Cap|WWNs|FabricWWN}
+ * @devs: Pointer to pool object table
+ *
+ * API specific:
+ * @sysfs_path: Sysfs path to search
+ * @cap: Capability name to search
+ * @wwnn & @wwpn: WWNN & WWPN name to search
+ * @fabric_wwn: Fabric_WWN to search
+ *
+ * Search by API specific argument in the table to return a pool object
+ * matching the argument specifics
+ *
+ * Returns: NULL if not found, a locked and ref'd object reference that
+ *          needs a virPoolObjEndAPI to clear
+ */
+virPoolObjPtr
+virNodeDeviceObjFindBySysfsPath(virPoolObjTablePtr devs,
+                                const char *sysfs_path)
+{
+    struct searchData data = { .sysfs_path = sysfs_path };
+
+    return virPoolObjTableSearchRef(devs, searchBySysfsPath, &data);
+}
+
+
+static virPoolObjPtr
+nodeDeviceFindByCap(virPoolObjTablePtr devs,
+                    const char *cap)
+{
+    struct searchData data = { .cap = cap };
+
+    return virPoolObjTableSearchRef(devs, searchByCap, &data);
+}
+
+
+static virPoolObjPtr
+nodeDeviceFindByWWNs(virPoolObjTablePtr devs,
+                     const char *parent_wwnn,
+                     const char *parent_wwpn)
+{
+    struct searchData data = { .parent_wwnn = parent_wwnn,
+                               .parent_wwpn = parent_wwpn };
+
+    return virPoolObjTableSearchRef(devs, searchByWWNs, &data);
+}
+
+
+static virPoolObjPtr
+nodeDeviceFindByFabricWWN(virPoolObjTablePtr devs,
+                          const char *parent_fabric_wwn)
+{
+    struct searchData data = { .parent_fabric_wwn = parent_fabric_wwn };
+
+    return virPoolObjTableSearchRef(devs, searchByFabricWWN, &data);
+}
+
+
+/*
+ * Return the NPIV dev's parent device name
+ */
+/* nodeDeviceFindFCParentHost:
+ * @def: Pointer to node device def
+ * @parent_host: Pointer to return parent host number
+ *
+ * Search the capabilities for the device to find the FC capabilities
+ * in order to set the parent_host value.
+ *
+ * Returns:
+ *   0 on success with parent_host set, -1 otherwise;
+ */
+static int
+nodeDeviceFindFCParentHost(const virNodeDeviceDef *def,
+                           int *parent_host)
+{
+    virNodeDevCapsDefPtr cap = nodeDeviceFindVPORTCapDef(def);
+
+    if (!cap) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Parent device %s is not capable "
+                         "of vport operations"),
+                       def->name);
+        return -1;
+    }
+
+    *parent_host = cap->data.scsi_host.host;
+    return 0;
+}
+
+
+int
+virNodeDeviceObjGetParentHost(virPoolObjTablePtr devs,
+                              const char *dev_name,
+                              const char *parent_name,
+                              int *parent_host)
+{
+    virPoolObjPtr obj;
+    virNodeDeviceDefPtr def;
+    int ret;
+
+    if (!(obj = virPoolObjTableFindByName(devs, parent_name))) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Could not find parent device for '%s'"),
+                       dev_name);
+        return -1;
+    }
+    def = virPoolObjGetDef(obj);
+
+    ret = nodeDeviceFindFCParentHost(def, parent_host);
+
+    virPoolObjEndAPI(&obj);
+    return ret;
+}
+
+
+int
+virNodeDeviceObjGetParentHostByWWNs(virPoolObjTablePtr devs,
+                                    const char *dev_name,
+                                    const char *parent_wwnn,
+                                    const char *parent_wwpn,
+                                    int *parent_host)
+{
+    virPoolObjPtr obj = NULL;
+    virNodeDeviceDefPtr def;
+    int ret;
+
+    if (!(obj = nodeDeviceFindByWWNs(devs, parent_wwnn, parent_wwpn))) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Could not find parent device for '%s'"),
+                       dev_name);
+        return -1;
+    }
+    def = virPoolObjGetDef(obj);
+
+    ret = nodeDeviceFindFCParentHost(def, parent_host);
+
+    virPoolObjEndAPI(&obj);
+
+    return ret;
+}
+
+
+int
+virNodeDeviceObjGetParentHostByFabricWWN(virPoolObjTablePtr devs,
+                                         const char *dev_name,
+                                         const char *parent_fabric_wwn,
+                                         int *parent_host)
+{
+    virPoolObjPtr obj;
+    virNodeDeviceDefPtr def;
+    int ret;
+
+    if (!(obj = nodeDeviceFindByFabricWWN(devs, parent_fabric_wwn))) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Could not find parent device for '%s'"),
+                       dev_name);
+        return -1;
+    }
+    def = virPoolObjGetDef(obj);
+
+    ret = nodeDeviceFindFCParentHost(def, parent_host);
+
+    virPoolObjEndAPI(&obj);
+
+    return ret;
+}
+
+
+int
+virNodeDeviceObjFindVportParentHost(virPoolObjTablePtr devs,
+                                    int *parent_host)
+{
+    virPoolObjPtr obj;
+    virNodeDeviceDefPtr def;
+    const char *cap = virNodeDevCapTypeToString(VIR_NODE_DEV_CAP_VPORTS);
+    int ret;
+
+    if (!(obj = nodeDeviceFindByCap(devs, cap))) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Could not find any vport capable device"));
+        return -1;
+    }
+    def = virPoolObjGetDef(obj);
+
+    ret = nodeDeviceFindFCParentHost(def, parent_host);
+
+    virPoolObjEndAPI(&obj);
+    return ret;
+}
+
+
+static bool
+nodeDeviceCapMatch(virPoolObjPtr obj,
+                   int type)
+{
+    virNodeDeviceDefPtr def = virPoolObjGetDef(obj);
+    virNodeDevCapsDefPtr cap = NULL;
+
+    for (cap = 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;
+}
+
+
+virPoolObjPtr
+virNodeDeviceObjFindByName(virPoolObjTablePtr devobjs,
+                           const char *name)
+{
+    virPoolObjPtr obj;
+
+    if (!(obj = virPoolObjTableFindByName(devobjs, name)))
+        virReportError(VIR_ERR_NO_NODE_DEVICE,
+                       _("no node device with matching name '%s'"),
+                       name);
+
+    return obj;
+}
+
+
+struct nodeCountData {
+    const char *cap;
+    int count;
+};
+
+static int
+nodeCount(virPoolObjPtr obj,
+          void *opaque)
+{
+    virNodeDeviceDefPtr def = virPoolObjGetDef(obj);
+    struct nodeCountData *data = opaque;
+
+    if (!data->cap || nodeDeviceHasCap(def, data->cap))
+        data->count++;
+
+    return 0;
+}
+
+
+int
+virNodeDeviceObjNumOfDevices(virPoolObjTablePtr devobjs,
+                             virConnectPtr conn,
+                             const char *cap,
+                             virPoolObjACLFilter aclfilter)
+{
+    struct nodeCountData data = { .cap = cap,
+                                  .count = 0 };
+
+    if (virPoolObjTableList(devobjs, conn, aclfilter, nodeCount, &data) < 0)
+        return 0;
+
+    return data.count;
+}
+
+
+struct nodedevNameData {
+    const char *cap;
+    int nnames;
+    char **const names;
+    int maxnames;
+};
+
+static int
+nodedevGetNames(virPoolObjPtr obj,
+                void *opaque)
+{
+    virNodeDeviceDefPtr def = virPoolObjGetDef(obj);
+    struct nodedevNameData *data = opaque;
+
+    if (data->nnames < data->maxnames) {
+        if (!data->cap || nodeDeviceHasCap(def, data->cap)) {
+            if (VIR_STRDUP(data->names[data->nnames++], def->name) < 0)
+                return -1;
+        }
+    }
+    return 0;
+}
+
+
+int
+virNodeDeviceObjGetNames(virPoolObjTablePtr devobjs,
+                         virConnectPtr conn,
+                         virPoolObjACLFilter aclfilter,
+                         const char *cap,
+                         char **const names,
+                         int maxnames)
+{
+    struct nodedevNameData data = { .cap = cap,
+                                    .nnames = 0,
+                                    .names = names,
+                                    .maxnames = maxnames };
+
+    if (virPoolObjTableList(devobjs, conn, aclfilter,
+                            nodedevGetNames, &data) < 0)
+        goto failure;
+
+    return data.nnames;
+
+ failure:
+    while (--data.nnames >= 0)
+        VIR_FREE(names[data.nnames]);
+    return -1;
+}
+
+
+#define MATCH(FLAG) ((flags & (VIR_CONNECT_LIST_NODE_DEVICES_CAP_ ## FLAG)) && \
+                     nodeDeviceCapMatch(obj, VIR_NODE_DEV_CAP_ ## FLAG))
+static bool
+nodeDeviceMatchFilter(virPoolObjPtr obj,
+                      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)))
+            return false;
+    }
+
+    return true;
+}
+#undef MATCH
+
+
+int
+virNodeDeviceObjExportList(virConnectPtr conn,
+                           virPoolObjTablePtr devobjs,
+                           virNodeDevicePtr **devices,
+                           virPoolObjACLFilter aclfilter,
+                           unsigned int flags)
+{
+    virPoolObjPtr *objs = NULL;
+    virNodeDevicePtr *devs = NULL;
+    size_t nobjs = 0;
+    int ret = -1;
+    size_t i;
+
+    if (virPoolObjTableCollect(devobjs, conn, &objs, &nobjs, aclfilter,
+                               nodeDeviceMatchFilter, flags) < 0)
+        return -1;
+
+    if (devices) {
+        if (VIR_ALLOC_N(devs, nobjs + 1) < 0)
+            goto cleanup;
+
+        for (i = 0; i < nobjs; i++) {
+            virPoolObjPtr obj = objs[i];
+            virNodeDeviceDefPtr def;
+
+            virObjectLock(obj);
+            def = virPoolObjGetDef(obj);
+            devs[i] = virGetNodeDevice(conn, def->name);
+            virObjectUnlock(obj);
+
+            if (!devs[i])
+                goto cleanup;
+        }
+
+        *devices = devs;
+        devs = NULL;
+    }
+
+    ret = nobjs;
+
+ cleanup:
+    virObjectListFree(devs);
+    virObjectListFreeCount(objs, nobjs);
+    return ret;
+}
diff --git a/src/conf/virnodedeviceobj.h b/src/conf/virnodedeviceobj.h
new file mode 100644
index 0000000..3359211
--- /dev/null
+++ b/src/conf/virnodedeviceobj.h
@@ -0,0 +1,86 @@
+/*
+ * 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 "virpoolobj.h"
+# include "virthread.h"
+
+# include "object_event.h"
+
+
+typedef struct _virNodeDeviceDriverState virNodeDeviceDriverState;
+typedef virNodeDeviceDriverState *virNodeDeviceDriverStatePtr;
+struct _virNodeDeviceDriverState {
+    virMutex lock;
+
+    virPoolObjTablePtr devs;		/* currently-known devices */
+    void *privateData;			/* driver-specific private data */
+
+    /* Immutable pointer, self-locking APIs */
+    virObjectEventStatePtr nodeDeviceEventState;
+};
+
+virPoolObjPtr virNodeDeviceObjFindBySysfsPath(virPoolObjTablePtr devs,
+                                              const char *sysfs_path)
+    ATTRIBUTE_NONNULL(2);
+
+int virNodeDeviceObjGetParentHost(virPoolObjTablePtr devs,
+                                  const char *dev_name,
+                                  const char *parent_name,
+                                  int *parent_host);
+
+int virNodeDeviceObjGetParentHostByWWNs(virPoolObjTablePtr devs,
+                                        const char *dev_name,
+                                        const char *parent_wwnn,
+                                        const char *parent_wwpn,
+                                        int *parent_host);
+
+int virNodeDeviceObjGetParentHostByFabricWWN(virPoolObjTablePtr devs,
+                                             const char *dev_name,
+                                             const char *parent_fabric_wwn,
+                                             int *parent_host);
+
+int virNodeDeviceObjFindVportParentHost(virPoolObjTablePtr devs,
+                                        int *parent_host);
+
+virPoolObjPtr virNodeDeviceObjFindByName(virPoolObjTablePtr devobjs,
+                                         const char *name);
+
+int virNodeDeviceObjNumOfDevices(virPoolObjTablePtr devobjs,
+                                 virConnectPtr conn,
+                                 const char *cap,
+                                 virPoolObjACLFilter aclfilter);
+
+int virNodeDeviceObjGetNames(virPoolObjTablePtr devobjs,
+                             virConnectPtr conn,
+                             virPoolObjACLFilter aclfilter,
+                             const char *cap,
+                             char **const names,
+                             int maxnames);
+
+int virNodeDeviceObjExportList(virConnectPtr conn,
+                               virPoolObjTablePtr devobjs,
+                               virNodeDevicePtr **devices,
+                               virPoolObjACLFilter aclfilter,
+                               unsigned int flags);
+
+#endif /* __VIRNODEDEVICEOBJ_H__ */
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 1f2157d..98b3840 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -694,25 +694,12 @@ virNetDevIPRouteParseXML;
 virNodeDevCapsDefFree;
 virNodeDevCapTypeFromString;
 virNodeDevCapTypeToString;
-virNodeDeviceAssignDef;
 virNodeDeviceDefFormat;
 virNodeDeviceDefFree;
 virNodeDeviceDefParseFile;
 virNodeDeviceDefParseNode;
 virNodeDeviceDefParseString;
-virNodeDeviceFindByName;
-virNodeDeviceFindBySysfsPath;
-virNodeDeviceFindVportParentHost;
-virNodeDeviceGetParentHost;
-virNodeDeviceGetParentHostByFabricWWN;
-virNodeDeviceGetParentHostByWWNs;
 virNodeDeviceGetWWNs;
-virNodeDeviceHasCap;
-virNodeDeviceObjListExport;
-virNodeDeviceObjListFree;
-virNodeDeviceObjLock;
-virNodeDeviceObjRemove;
-virNodeDeviceObjUnlock;
 
 
 # conf/node_device_event.h
@@ -961,6 +948,18 @@ virDomainObjListRemoveLocked;
 virDomainObjListRename;
 
 
+# conf/virnodedeviceobj.h
+virNodeDeviceObjExportList;
+virNodeDeviceObjFindByName;
+virNodeDeviceObjFindBySysfsPath;
+virNodeDeviceObjFindVportParentHost;
+virNodeDeviceObjGetNames;
+virNodeDeviceObjGetParentHost;
+virNodeDeviceObjGetParentHostByFabricWWN;
+virNodeDeviceObjGetParentHostByWWNs;
+virNodeDeviceObjNumOfDevices;
+
+
 # conf/virpoolobj.h
 virPoolObjEndAPI;
 virPoolObjGetDef;
diff --git a/src/node_device/node_device_driver.c b/src/node_device/node_device_driver.c
index 5238e23..f7e460c 100644
--- a/src/node_device/node_device_driver.c
+++ b/src/node_device/node_device_driver.c
@@ -42,19 +42,22 @@
 #include "virutil.h"
 #include "viraccessapicheck.h"
 #include "virnetdev.h"
+#include "virpoolobj.h"
 
 #define VIR_FROM_THIS VIR_FROM_NODEDEV
 
 virNodeDeviceDriverStatePtr driver;
 
-static int update_caps(virNodeDeviceObjPtr dev)
+static int
+update_caps(virPoolObjPtr obj)
 {
-    virNodeDevCapsDefPtr cap = dev->def->caps;
+    virNodeDeviceDefPtr def = virPoolObjGetDef(obj);
+    virNodeDevCapsDefPtr cap = def->caps;
 
     while (cap) {
         switch (cap->data.type) {
         case VIR_NODE_DEV_CAP_SCSI_HOST:
-            nodeDeviceSysfsGetSCSIHostCaps(&dev->def->caps->data);
+            nodeDeviceSysfsGetSCSIHostCaps(&def->caps->data);
             break;
         case VIR_NODE_DEV_CAP_NET:
             if (virNetDevGetLinkInfo(cap->data.net.ifname, &cap->data.net.lnk) < 0)
@@ -64,8 +67,8 @@ static int update_caps(virNodeDeviceObjPtr dev)
                 return -1;
             break;
         case VIR_NODE_DEV_CAP_PCI_DEV:
-           if (nodeDeviceSysfsGetPCIRelatedDevCaps(dev->def->sysfs_path,
-                                                   &dev->def->caps->data) < 0)
+           if (nodeDeviceSysfsGetPCIRelatedDevCaps(def->sysfs_path,
+                                                   &def->caps->data) < 0)
               return -1;
            break;
 
@@ -100,16 +103,18 @@ static int update_caps(virNodeDeviceObjPtr dev)
  * the driver name for a device each time its entry is used, both for
  * udev *and* HAL backends.
  */
-static int update_driver_name(virNodeDeviceObjPtr dev)
+static int
+update_driver_name(virPoolObjPtr obj)
 {
+    virNodeDeviceDefPtr def = virPoolObjGetDef(obj);
     char *driver_link = NULL;
     char *devpath = NULL;
     char *p;
     int ret = -1;
 
-    VIR_FREE(dev->def->driver);
+    VIR_FREE(def->driver);
 
-    if (virAsprintf(&driver_link, "%s/driver", dev->def->sysfs_path) < 0)
+    if (virAsprintf(&driver_link, "%s/driver", def->sysfs_path) < 0)
         goto cleanup;
 
     /* Some devices don't have an explicit driver, so just return
@@ -126,7 +131,7 @@ static int update_driver_name(virNodeDeviceObjPtr dev)
     }
 
     p = strrchr(devpath, '/');
-    if (p && VIR_STRDUP(dev->def->driver, p + 1) < 0)
+    if (p && VIR_STRDUP(def->driver, p + 1) < 0)
         goto cleanup;
     ret = 0;
 
@@ -137,7 +142,7 @@ static int update_driver_name(virNodeDeviceObjPtr dev)
 }
 #else
 /* XXX: Implement me for non-linux */
-static int update_driver_name(virNodeDeviceObjPtr dev ATTRIBUTE_UNUSED)
+static int update_driver_name(virPoolObjPtr obj ATTRIBUTE_UNUSED)
 {
     return 0;
 }
@@ -153,74 +158,41 @@ void nodeDeviceUnlock(void)
     virMutexUnlock(&driver->lock);
 }
 
+/* Node device implementations */
+
 int
 nodeNumOfDevices(virConnectPtr conn,
                  const char *cap,
                  unsigned int flags)
 {
-    int ndevs = 0;
-    size_t i;
+    virCheckFlags(0, -1);
 
     if (virNodeNumOfDevicesEnsureACL(conn) < 0)
         return -1;
 
-    virCheckFlags(0, -1);
-
-    nodeDeviceLock();
-    for (i = 0; i < driver->devs.count; i++) {
-        virNodeDeviceObjPtr obj = driver->devs.objs[i];
-        virNodeDeviceObjLock(obj);
-        if (virNodeNumOfDevicesCheckACL(conn, obj->def) &&
-            ((cap == NULL) ||
-             virNodeDeviceHasCap(obj, cap)))
-            ++ndevs;
-        virNodeDeviceObjUnlock(obj);
-    }
-    nodeDeviceUnlock();
-
-    return ndevs;
+    return virNodeDeviceObjNumOfDevices(driver->devs, conn, cap,
+                                        virNodeNumOfDevicesCheckACL);
 }
 
+
 int
 nodeListDevices(virConnectPtr conn,
                 const char *cap,
-                char **const names, int maxnames,
+                char **const names,
+                int maxnames,
                 unsigned int flags)
 {
-    int ndevs = 0;
-    size_t i;
+    virCheckFlags(0, -1);
 
     if (virNodeListDevicesEnsureACL(conn) < 0)
         return -1;
 
-    virCheckFlags(0, -1);
-
-    nodeDeviceLock();
-    for (i = 0; i < driver->devs.count && ndevs < maxnames; i++) {
-        virNodeDeviceObjPtr obj = driver->devs.objs[i];
-        virNodeDeviceObjLock(obj);
-        if (virNodeListDevicesCheckACL(conn, obj->def) &&
-            (cap == NULL ||
-             virNodeDeviceHasCap(obj, cap))) {
-            if (VIR_STRDUP(names[ndevs++], obj->def->name) < 0) {
-                virNodeDeviceObjUnlock(obj);
-                goto failure;
-            }
-        }
-        virNodeDeviceObjUnlock(obj);
-    }
-    nodeDeviceUnlock();
-
-    return ndevs;
-
- failure:
-    nodeDeviceUnlock();
-    --ndevs;
-    while (--ndevs >= 0)
-        VIR_FREE(names[ndevs]);
-    return -1;
+    return virNodeDeviceObjGetNames(driver->devs, conn,
+                                    virNodeListDevicesCheckACL,
+                                    cap, names, maxnames);
 }
 
+
 int
 nodeConnectListAllNodeDevices(virConnectPtr conn,
                               virNodeDevicePtr **devices,
@@ -233,89 +205,92 @@ nodeConnectListAllNodeDevices(virConnectPtr conn,
     if (virConnectListAllNodeDevicesEnsureACL(conn) < 0)
         return -1;
 
-    nodeDeviceLock();
-    ret = virNodeDeviceObjListExport(conn, driver->devs, devices,
+    ret = virNodeDeviceObjExportList(conn, driver->devs, devices,
                                      virConnectListAllNodeDevicesCheckACL,
                                      flags);
-    nodeDeviceUnlock();
     return ret;
 }
 
+
 virNodeDevicePtr
 nodeDeviceLookupByName(virConnectPtr conn, const char *name)
 {
-    virNodeDeviceObjPtr obj;
+    virPoolObjPtr obj;
+    virNodeDeviceDefPtr def;
     virNodeDevicePtr ret = NULL;
 
-    nodeDeviceLock();
-    obj = virNodeDeviceFindByName(&driver->devs, name);
-    nodeDeviceUnlock();
-
-    if (!obj) {
-        virReportError(VIR_ERR_NO_NODE_DEVICE,
-                       _("no node device with matching name '%s'"),
-                       name);
-        goto cleanup;
-    }
+    if (!(obj = virNodeDeviceObjFindByName(driver->devs, name)))
+        return NULL;
+    def = virPoolObjGetDef(obj);
 
-    if (virNodeDeviceLookupByNameEnsureACL(conn, obj->def) < 0)
+    if (virNodeDeviceLookupByNameEnsureACL(conn, def) < 0)
         goto cleanup;
 
     ret = virGetNodeDevice(conn, name);
 
  cleanup:
-    if (obj)
-        virNodeDeviceObjUnlock(obj);
+    virPoolObjEndAPI(&obj);
     return ret;
 }
 
 
+struct nodeDeviceSearchData {
+    const char *wwnn;
+    const char *wwpn;
+};
+
+static bool
+nodeLookupSCSIHostByWWN(virPoolObjPtr obj,
+                        void *opaque)
+{
+    virNodeDeviceDefPtr def = virPoolObjGetDef(obj);
+    struct nodeDeviceSearchData *data = opaque;
+    virNodeDevCapsDefPtr cap;
+
+    for (cap = def->caps; cap; cap = cap->next) {
+        if (cap->data.type != VIR_NODE_DEV_CAP_SCSI_HOST)
+            continue;
+
+        nodeDeviceSysfsGetSCSIHostCaps(&cap->data);
+        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)) {
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+
 virNodeDevicePtr
 nodeDeviceLookupSCSIHostByWWN(virConnectPtr conn,
                               const char *wwnn,
                               const char *wwpn,
                               unsigned int flags)
 {
-    size_t i;
-    virNodeDeviceObjListPtr devs = &driver->devs;
-    virNodeDevCapsDefPtr cap = NULL;
-    virNodeDeviceObjPtr obj = NULL;
+    virPoolObjPtr obj;
+    virNodeDeviceDefPtr def;
     virNodeDevicePtr dev = NULL;
+    struct nodeDeviceSearchData data = { .wwnn = wwnn,
+                                         .wwpn = wwpn };
 
     virCheckFlags(0, NULL);
 
-    nodeDeviceLock();
+    if (!(obj = virPoolObjTableSearchRef(driver->devs, nodeLookupSCSIHostByWWN,
+                                         &data)))
+        return NULL;
+    def = virPoolObjGetDef(obj);
 
-    for (i = 0; i < devs->count; i++) {
-        obj = devs->objs[i];
-        virNodeDeviceObjLock(obj);
-        cap = obj->def->caps;
-
-        while (cap) {
-            if (cap->data.type == VIR_NODE_DEV_CAP_SCSI_HOST) {
-                nodeDeviceSysfsGetSCSIHostCaps(&cap->data);
-                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)) {
-
-                        if (virNodeDeviceLookupSCSIHostByWWNEnsureACL(conn, obj->def) < 0)
-                            goto out;
-
-                        dev = virGetNodeDevice(conn, obj->def->name);
-                        virNodeDeviceObjUnlock(obj);
-                        goto out;
-                    }
-                }
-            }
-            cap = cap->next;
-        }
+    if (virNodeDeviceLookupSCSIHostByWWNEnsureACL(conn, def) < 0)
+        goto cleanup;
 
-        virNodeDeviceObjUnlock(obj);
-    }
+    dev = virGetNodeDevice(conn, def->name);
 
- out:
-    nodeDeviceUnlock();
+ cleanup:
+    virPoolObjEndAPI(&obj);
     return dev;
 }
 
@@ -324,34 +299,27 @@ char *
 nodeDeviceGetXMLDesc(virNodeDevicePtr dev,
                      unsigned int flags)
 {
-    virNodeDeviceObjPtr obj;
+    virPoolObjPtr obj;
+    virNodeDeviceDefPtr def;
     char *ret = NULL;
 
     virCheckFlags(0, NULL);
 
-    nodeDeviceLock();
-    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
-    nodeDeviceUnlock();
-
-    if (!obj) {
-        virReportError(VIR_ERR_NO_NODE_DEVICE,
-                       _("no node device with matching name '%s'"),
-                       dev->name);
-        goto cleanup;
-    }
+    if (!(obj = virNodeDeviceObjFindByName(driver->devs, dev->name)))
+        return NULL;
+    def = virPoolObjGetDef(obj);
 
-    if (virNodeDeviceGetXMLDescEnsureACL(dev->conn, obj->def) < 0)
+    if (virNodeDeviceGetXMLDescEnsureACL(dev->conn, def) < 0)
         goto cleanup;
 
     update_driver_name(obj);
     if (update_caps(obj) < 0)
         goto cleanup;
 
-    ret = virNodeDeviceDefFormat(obj->def);
+    ret = virNodeDeviceDefFormat(def);
 
  cleanup:
-    if (obj)
-        virNodeDeviceObjUnlock(obj);
+    virPoolObjEndAPI(&obj);
     return ret;
 }
 
@@ -359,25 +327,19 @@ nodeDeviceGetXMLDesc(virNodeDevicePtr dev,
 char *
 nodeDeviceGetParent(virNodeDevicePtr dev)
 {
-    virNodeDeviceObjPtr obj;
+    virPoolObjPtr obj;
+    virNodeDeviceDefPtr def;
     char *ret = NULL;
 
-    nodeDeviceLock();
-    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
-    nodeDeviceUnlock();
-
-    if (!obj) {
-        virReportError(VIR_ERR_NO_NODE_DEVICE,
-                       _("no node device with matching name '%s'"),
-                       dev->name);
-        goto cleanup;
-    }
+    if (!(obj = virNodeDeviceObjFindByName(driver->devs, dev->name)))
+        return NULL;
+    def = virPoolObjGetDef(obj);
 
-    if (virNodeDeviceGetParentEnsureACL(dev->conn, obj->def) < 0)
+    if (virNodeDeviceGetParentEnsureACL(dev->conn, def) < 0)
         goto cleanup;
 
-    if (obj->def->parent) {
-        if (VIR_STRDUP(ret, obj->def->parent) < 0)
+    if (def->parent) {
+        if (VIR_STRDUP(ret, def->parent) < 0)
             goto cleanup;
     } else {
         virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -385,8 +347,7 @@ nodeDeviceGetParent(virNodeDevicePtr dev)
     }
 
  cleanup:
-    if (obj)
-        virNodeDeviceObjUnlock(obj);
+    virPoolObjEndAPI(&obj);
     return ret;
 }
 
@@ -394,26 +355,20 @@ nodeDeviceGetParent(virNodeDevicePtr dev)
 int
 nodeDeviceNumOfCaps(virNodeDevicePtr dev)
 {
-    virNodeDeviceObjPtr obj;
+    virPoolObjPtr obj;
+    virNodeDeviceDefPtr def;
     virNodeDevCapsDefPtr caps;
     int ncaps = 0;
     int ret = -1;
 
-    nodeDeviceLock();
-    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
-    nodeDeviceUnlock();
-
-    if (!obj) {
-        virReportError(VIR_ERR_NO_NODE_DEVICE,
-                       _("no node device with matching name '%s'"),
-                       dev->name);
-        goto cleanup;
-    }
+    if (!(obj = virNodeDeviceObjFindByName(driver->devs, dev->name)))
+        return -1;
+    def = virPoolObjGetDef(obj);
 
-    if (virNodeDeviceNumOfCapsEnsureACL(dev->conn, obj->def) < 0)
+    if (virNodeDeviceNumOfCapsEnsureACL(dev->conn, def) < 0)
         goto cleanup;
 
-    for (caps = obj->def->caps; caps; caps = caps->next) {
+    for (caps = def->caps; caps; caps = caps->next) {
         ++ncaps;
 
         if (caps->data.type == VIR_NODE_DEV_CAP_SCSI_HOST) {
@@ -430,36 +385,32 @@ nodeDeviceNumOfCaps(virNodeDevicePtr dev)
     ret = ncaps;
 
  cleanup:
-    if (obj)
-        virNodeDeviceObjUnlock(obj);
+    virPoolObjEndAPI(&obj);
     return ret;
 }
 
 
 int
-nodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames)
+nodeDeviceListCaps(virNodeDevicePtr dev,
+                   char **const names,
+                   int maxnames)
 {
-    virNodeDeviceObjPtr obj;
+    virPoolObjPtr obj;
+    virNodeDeviceDefPtr def;
     virNodeDevCapsDefPtr caps;
     int ncaps = 0;
     int ret = -1;
 
-    nodeDeviceLock();
-    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
-    nodeDeviceUnlock();
-
-    if (!obj) {
-        virReportError(VIR_ERR_NO_NODE_DEVICE,
-                       _("no node device with matching name '%s'"),
-                       dev->name);
-        goto cleanup;
-    }
+    if (!(obj = virNodeDeviceObjFindByName(driver->devs, dev->name)))
+        return -1;
+    def = virPoolObjGetDef(obj);
 
-    if (virNodeDeviceListCapsEnsureACL(dev->conn, obj->def) < 0)
+    if (virNodeDeviceListCapsEnsureACL(dev->conn, def) < 0)
         goto cleanup;
 
-    for (caps = obj->def->caps; caps && ncaps < maxnames; caps = caps->next) {
-        if (VIR_STRDUP(names[ncaps++], virNodeDevCapTypeToString(caps->data.type)) < 0)
+    for (caps = def->caps; caps && ncaps < maxnames; caps = caps->next) {
+        if (VIR_STRDUP(names[ncaps++],
+                       virNodeDevCapTypeToString(caps->data.type)) < 0)
             goto cleanup;
 
         if (caps->data.type == VIR_NODE_DEV_CAP_SCSI_HOST) {
@@ -483,8 +434,7 @@ nodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames)
     ret = ncaps;
 
  cleanup:
-    if (obj)
-        virNodeDeviceObjUnlock(obj);
+    virPoolObjEndAPI(&obj);
     if (ret == -1) {
         --ncaps;
         while (--ncaps >= 0)
@@ -573,9 +523,7 @@ nodeDeviceCreateXML(virConnectPtr conn,
     virt_type  = virConnectGetType(conn);
 
     nodeDeviceLock();
-
-    def = virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE, virt_type);
-    if (def == NULL)
+    if (!(def = virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE, virt_type)))
         goto cleanup;
 
     if (virNodeDeviceCreateXMLEnsureACL(conn, def) < 0)
@@ -585,36 +533,35 @@ nodeDeviceCreateXML(virConnectPtr conn,
         goto cleanup;
 
     if (def->parent) {
-        if (virNodeDeviceGetParentHost(&driver->devs,
-                                       def->name,
-                                       def->parent,
-                                       &parent_host) < 0)
+        if (virNodeDeviceObjGetParentHost(driver->devs,
+                                          def->name,
+                                          def->parent,
+                                          &parent_host) < 0)
             goto cleanup;
     } else if (def->parent_wwnn && def->parent_wwpn) {
-        if (virNodeDeviceGetParentHostByWWNs(&driver->devs,
-                                             def->name,
-                                             def->parent_wwnn,
-                                             def->parent_wwpn,
-                                             &parent_host) < 0)
+        if (virNodeDeviceObjGetParentHostByWWNs(driver->devs,
+                                                def->name,
+                                                def->parent_wwnn,
+                                                def->parent_wwpn,
+                                                &parent_host) < 0)
             goto cleanup;
     } else if (def->parent_fabric_wwn) {
-        if (virNodeDeviceGetParentHostByFabricWWN(&driver->devs,
-                                                  def->name,
-                                                  def->parent_fabric_wwn,
-                                                  &parent_host) < 0)
+        if (virNodeDeviceObjGetParentHostByFabricWWN(driver->devs,
+                                                     def->name,
+                                                     def->parent_fabric_wwn,
+                                                     &parent_host) < 0)
             goto cleanup;
     } else {
         /* Try to find a vport capable scsi_host when no parent supplied */
-        if (virNodeDeviceFindVportParentHost(&driver->devs, &parent_host) < 0)
+        if (virNodeDeviceObjFindVportParentHost(driver->devs, &parent_host) < 0)
             goto cleanup;
     }
 
     if (virManageVport(parent_host,
                        wwpn,
                        wwnn,
-                       VPORT_CREATE) == -1) {
+                       VPORT_CREATE) == -1)
         goto cleanup;
-    }
 
     dev = find_new_device(conn, wwnn, wwpn);
     /* We don't check the return value, because one way or another,
@@ -638,64 +585,45 @@ int
 nodeDeviceDestroy(virNodeDevicePtr dev)
 {
     int ret = -1;
-    virNodeDeviceObjPtr obj = NULL;
-    char *parent_name = NULL, *wwnn = NULL, *wwpn = NULL;
+    virPoolObjPtr obj;
+    virNodeDeviceDefPtr def;
+    char *wwnn = NULL;
+    char *wwpn = NULL;
     int parent_host = -1;
 
-    nodeDeviceLock();
-    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
-    nodeDeviceUnlock();
-
-    if (!obj) {
-        virReportError(VIR_ERR_NO_NODE_DEVICE,
-                       _("no node device with matching name '%s'"),
-                       dev->name);
-        goto out;
-    }
-
-    if (virNodeDeviceDestroyEnsureACL(dev->conn, obj->def) < 0)
-        goto out;
+    if (!(obj = virNodeDeviceObjFindByName(driver->devs, dev->name)))
+        return -1;
+    def = virPoolObjGetDef(obj);
 
-    if (virNodeDeviceGetWWNs(obj->def, &wwnn, &wwpn) == -1)
-        goto out;
+    if (virNodeDeviceDestroyEnsureACL(dev->conn, def) < 0)
+        goto cleanup;
 
+    if (virNodeDeviceGetWWNs(def, &wwnn, &wwpn) == -1)
+        goto cleanup;
 
-    /* virNodeDeviceGetParentHost will cause the device object's lock to be
-     * taken, so we have to dup the parent's name and drop the lock
-     * before calling it.  We don't need the reference to the object
-     * any more once we have the parent's name.  */
-    if (VIR_STRDUP(parent_name, obj->def->parent) < 0) {
-        virNodeDeviceObjUnlock(obj);
-        obj = NULL;
-        goto out;
-    }
-    virNodeDeviceObjUnlock(obj);
-    obj = NULL;
-
-    if (virNodeDeviceGetParentHost(&driver->devs,
-                                   dev->name,
-                                   parent_name,
-                                   &parent_host) == -1) {
-        goto out;
-    }
+    if (virNodeDeviceObjGetParentHost(driver->devs,
+                                      dev->name,
+                                      def->parent,
+                                      &parent_host) == -1)
+        goto cleanup;
 
     if (virManageVport(parent_host,
                        wwpn,
                        wwnn,
-                       VPORT_DELETE) == -1) {
-        goto out;
-    }
+                       VPORT_DELETE) == -1)
+        goto cleanup;
+
+    virPoolObjTableRemove(driver->devs, &obj);
 
     ret = 0;
- out:
-    if (obj)
-        virNodeDeviceObjUnlock(obj);
-    VIR_FREE(parent_name);
+ cleanup:
+    virPoolObjEndAPI(&obj);
     VIR_FREE(wwnn);
     VIR_FREE(wwpn);
     return ret;
 }
 
+
 int
 nodeConnectNodeDeviceEventRegisterAny(virConnectPtr conn,
                                       virNodeDevicePtr dev,
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/node_device/node_device_hal.c b/src/node_device/node_device_hal.c
index fb7bf25..70c37c9 100644
--- a/src/node_device/node_device_hal.c
+++ b/src/node_device/node_device_hal.c
@@ -52,9 +52,6 @@ VIR_LOG_INIT("node_device.node_device_hal");
 
 #define DRV_STATE_HAL_CTX(ds) ((LibHalContext *)((ds)->privateData))
 
-#define NODE_DEV_UDI(obj) ((const char *)((obj)->privateData)
-
-
 static const char *
 hal_name(const char *udi)
 {
@@ -446,27 +443,18 @@ gather_capabilities(LibHalContext *ctx, const char *udi,
     return rv;
 }
 
-static void
-free_udi(void *udi)
-{
-    VIR_FREE(udi);
-}
 
 static void
 dev_create(const char *udi)
 {
     LibHalContext *ctx;
     char *parent_key = NULL;
-    virNodeDeviceObjPtr dev = NULL;
+    virPoolObjPtr obj = NULL;
     virNodeDeviceDefPtr def = NULL;
     const char *name = hal_name(udi);
     int rv;
-    char *privData;
     char *devicePath = NULL;
 
-    if (VIR_STRDUP(privData, udi) < 0)
-        return;
-
     nodeDeviceLock();
     ctx = DRV_STATE_HAL_CTX(driver);
 
@@ -492,29 +480,23 @@ dev_create(const char *udi)
 
     /* Some devices don't have a path in sysfs, so ignore failure */
     (void)get_str_prop(ctx, udi, "linux.sysfs_path", &devicePath);
+    VIR_STEAL_PTR(def->sysfs_path, devicePath);
 
-    dev = virNodeDeviceAssignDef(&driver->devs,
-                                 def);
-
-    if (!dev) {
-        VIR_FREE(devicePath);
+    if (!(obj = virPoolObjTableAdd(driver->devs, NULL, def->name,
+                                   def, NULL, NULL, virNodeDeviceDefFree,
+                                   NULL, 0)))
         goto failure;
-    }
-
-    dev->privateData = privData;
-    dev->privateFree = free_udi;
-    dev->def->sysfs_path = devicePath;
-
-    virNodeDeviceObjUnlock(dev);
+    def = NULL;
 
+    virPoolObjEndAPI(&obj);
     nodeDeviceUnlock();
     return;
 
  failure:
     VIR_DEBUG("FAILED TO ADD dev %s", name);
  cleanup:
-    VIR_FREE(privData);
     virNodeDeviceDefFree(def);
+    virPoolObjEndAPI(&obj);
     nodeDeviceUnlock();
 }
 
@@ -522,19 +504,17 @@ static void
 dev_refresh(const char *udi)
 {
     const char *name = hal_name(udi);
-    virNodeDeviceObjPtr dev;
+    virPoolObjPtr obj;
 
-    nodeDeviceLock();
-    dev = virNodeDeviceFindByName(&driver->devs, name);
-    if (dev) {
+    if ((obj = virPoolObjTableFindByName(driver->devs, name))) {
         /* Simply "rediscover" device -- incrementally handling changes
          * to sub-capabilities (like net.80203) is nasty ... so avoid it.
          */
-        virNodeDeviceObjRemove(&driver->devs, &dev);
+        virPoolObjTableObjRemove(driver->devs, &obj);
     } else {
         VIR_DEBUG("no device named %s", name);
     }
-    nodeDeviceUnlock();
+    virPoolObjEndAPI(&obj);
 
     if (dev)
         dev_create(udi);
@@ -554,16 +534,14 @@ device_removed(LibHalContext *ctx ATTRIBUTE_UNUSED,
                const char *udi)
 {
     const char *name = hal_name(udi);
-    virNodeDeviceObjPtr dev;
+    virPoolObjPtr obj;
 
-    nodeDeviceLock();
-    dev = virNodeDeviceFindByName(&driver->devs, name);
     VIR_DEBUG("%s", name);
-    if (dev)
-        virNodeDeviceObjRemove(&driver->devs, &dev);
+    if ((obj = virPoolObjTableFindByName(driver->devs, name)))
+        virPoolObjTableRemove(driver->devs, &obj);
     else
         VIR_DEBUG("no device named %s", name);
-    nodeDeviceUnlock();
+    virPoolObjEndAPI(&obj);
 }
 
 
@@ -572,18 +550,18 @@ device_cap_added(LibHalContext *ctx,
                  const char *udi, const char *cap)
 {
     const char *name = hal_name(udi);
-    virNodeDeviceObjPtr dev;
+    virPoolObjPtr obj;
+    virNodeDeviceDefPtr def;
 
-    nodeDeviceLock();
-    dev = virNodeDeviceFindByName(&driver->devs, name);
-    nodeDeviceUnlock();
     VIR_DEBUG("%s %s", cap, name);
-    if (dev) {
-        (void)gather_capability(ctx, udi, cap, &dev->def->caps);
-        virNodeDeviceObjUnlock(dev);
+
+    if ((obj = virPoolObjTableFindByName(driver->devs, name))) {
+        def = virPoolObjGetDef(obj);
+        (void)gather_capability(ctx, udi, cap, &def->caps);
     } else {
         VIR_DEBUG("no device named %s", name);
     }
+    virPoolObjEndAPI(&obj);
 }
 
 
@@ -639,6 +617,11 @@ nodeStateInitialize(bool privileged ATTRIBUTE_UNUSED,
     }
     nodeDeviceLock();
 
+    if (!(driver->devs =
+          virPoolObjTableNew(VIR_POOLOBJTABLE_NODEDEVICE,
+                             VIR_POOLOBJTABLE_NODEDEVICE_HASHSTART, true)))
+        goto cleanup;
+
     dbus_error_init(&err);
     if (!(sysbus = virDBusGetSystemBus())) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -713,9 +696,9 @@ nodeStateInitialize(bool privileged ATTRIBUTE_UNUSED,
                        _("%s: %s"), err.name, err.message);
         dbus_error_free(&err);
     }
-    virNodeDeviceObjListFree(&driver->devs);
     if (hal_ctx)
         (void)libhal_ctx_free(hal_ctx);
+    virObjectUnref(driver->devs);
     nodeDeviceUnlock();
     VIR_FREE(driver);
 
@@ -729,7 +712,7 @@ nodeStateCleanup(void)
     if (driver) {
         nodeDeviceLock();
         LibHalContext *hal_ctx = DRV_STATE_HAL_CTX(driver);
-        virNodeDeviceObjListFree(&driver->devs);
+        virObjectUnref(driver->devs);
         (void)libhal_ctx_shutdown(hal_ctx, NULL);
         (void)libhal_ctx_free(hal_ctx);
         nodeDeviceUnlock();
@@ -751,10 +734,9 @@ nodeStateReload(void)
     LibHalContext *hal_ctx;
 
     VIR_INFO("Reloading HAL device state");
-    nodeDeviceLock();
+
     VIR_INFO("Removing existing objects");
-    virNodeDeviceObjListFree(&driver->devs);
-    nodeDeviceUnlock();
+    virPoolObjTableClearAll(driver->devs);
 
     hal_ctx = DRV_STATE_HAL_CTX(driver);
     VIR_INFO("Creating new objects");
diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c
index 4b81312..33e8cc7 100644
--- a/src/node_device/node_device_udev.c
+++ b/src/node_device/node_device_udev.c
@@ -43,6 +43,7 @@
 #include "virpci.h"
 #include "virstring.h"
 #include "virnetdev.h"
+#include "virpoolobj.h"
 
 #define VIR_FROM_THIS VIR_FROM_NODEDEV
 
@@ -1024,32 +1025,34 @@ static int udevGetDeviceDetails(struct udev_device *device,
 
 static int udevRemoveOneDevice(struct udev_device *device)
 {
-    virNodeDeviceObjPtr dev = NULL;
+    virPoolObjPtr obj = NULL;
+    virNodeDeviceDefPtr def;
     virObjectEventPtr event = NULL;
     const char *name = NULL;
     int ret = -1;
 
     name = udev_device_get_syspath(device);
-    dev = virNodeDeviceFindBySysfsPath(&driver->devs, name);
 
-    if (!dev) {
+    if (!(obj = virNodeDeviceObjFindBySysfsPath(driver->devs, name))) {
         VIR_DEBUG("Failed to find device to remove that has udev name '%s'",
                   name);
         goto cleanup;
     }
 
-    event = virNodeDeviceEventLifecycleNew(dev->def->name,
+    def = virPoolObjGetDef(obj);
+    event = virNodeDeviceEventLifecycleNew(def->name,
                                            VIR_NODE_DEVICE_EVENT_DELETED,
                                            0);
 
     VIR_DEBUG("Removing device '%s' with sysfs path '%s'",
-              dev->def->name, name);
-    virNodeDeviceObjRemove(&driver->devs, &dev);
+              def->name, name);
+    virPoolObjTableRemove(driver->devs, &obj);
 
     ret = 0;
  cleanup:
     if (event)
         virObjectEventStateQueue(driver->nodeDeviceEventState, event);
+    virPoolObjEndAPI(&obj);
     return ret;
 }
 
@@ -1059,7 +1062,7 @@ static int udevSetParent(struct udev_device *device,
 {
     struct udev_device *parent_device = NULL;
     const char *parent_sysfs_path = NULL;
-    virNodeDeviceObjPtr dev = NULL;
+    virPoolObjPtr obj = NULL;
     int ret = -1;
 
     parent_device = device;
@@ -1077,14 +1080,11 @@ static int udevSetParent(struct udev_device *device,
             goto cleanup;
         }
 
-        dev = virNodeDeviceFindBySysfsPath(&driver->devs,
-                                           parent_sysfs_path);
-        if (dev != NULL) {
-            if (VIR_STRDUP(def->parent, dev->def->name) < 0) {
-                virNodeDeviceObjUnlock(dev);
+        if ((obj = virNodeDeviceObjFindBySysfsPath(driver->devs,
+                                                   parent_sysfs_path))) {
+            virNodeDeviceDefPtr objdef = virPoolObjGetDef(obj);
+            if (VIR_STRDUP(def->parent, objdef->name) < 0)
                 goto cleanup;
-            }
-            virNodeDeviceObjUnlock(dev);
 
             if (VIR_STRDUP(def->parent_sysfs_path, parent_sysfs_path) < 0)
                 goto cleanup;
@@ -1098,6 +1098,7 @@ static int udevSetParent(struct udev_device *device,
     ret = 0;
 
  cleanup:
+    virPoolObjEndAPI(&obj);
     return ret;
 }
 
@@ -1105,7 +1106,8 @@ static int udevSetParent(struct udev_device *device,
 static int udevAddOneDevice(struct udev_device *device)
 {
     virNodeDeviceDefPtr def = NULL;
-    virNodeDeviceObjPtr dev = NULL;
+    virPoolObjPtr obj = NULL;
+    virNodeDeviceDefPtr newdef;
     virObjectEventPtr event = NULL;
     bool new_device = true;
     int ret = -1;
@@ -1128,29 +1130,37 @@ static int udevAddOneDevice(struct udev_device *device)
     if (udevGetDeviceDetails(device, def) != 0)
         goto cleanup;
 
+    if (!def->name) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Did not generate def->name for '%s'"),
+                       udev_device_get_syspath(device));
+        goto cleanup;
+    }
+
     if (udevSetParent(device, def) != 0)
         goto cleanup;
 
-    dev = virNodeDeviceFindByName(&driver->devs, def->name);
-    if (dev) {
-        virNodeDeviceObjUnlock(dev);
+    if ((obj = virPoolObjTableFindByName(driver->devs, def->name))) {
+        virPoolObjEndAPI(&obj);
         new_device = false;
     }
 
     /* If this is a device change, the old definition will be freed
      * and the current definition will take its place. */
-    dev = virNodeDeviceAssignDef(&driver->devs, def);
-    if (dev == NULL)
+    if (!(obj = virPoolObjTableAdd(driver->devs, NULL, def->name,
+                                   def, NULL, NULL, virNodeDeviceDefFree,
+                                   NULL, 0)))
         goto cleanup;
+    VIR_STEAL_PTR(newdef, def);
 
     if (new_device)
-        event = virNodeDeviceEventLifecycleNew(dev->def->name,
+        event = virNodeDeviceEventLifecycleNew(newdef->name,
                                                VIR_NODE_DEVICE_EVENT_CREATED,
                                                0);
     else
-        event = virNodeDeviceEventUpdateNew(dev->def->name);
+        event = virNodeDeviceEventUpdateNew(newdef->name);
 
-    virNodeDeviceObjUnlock(dev);
+    virPoolObjEndAPI(&obj);
 
     ret = 0;
 
@@ -1288,7 +1298,7 @@ static int nodeStateCleanup(void)
     if (udev != NULL)
         udev_unref(udev);
 
-    virNodeDeviceObjListFree(&driver->devs);
+    virObjectUnref(driver->devs);
     nodeDeviceUnlock();
     virMutexDestroy(&driver->lock);
     VIR_FREE(driver);
@@ -1404,7 +1414,7 @@ udevGetDMIData(virNodeDevCapDataPtr data)
 static int udevSetupSystemDev(void)
 {
     virNodeDeviceDefPtr def = NULL;
-    virNodeDeviceObjPtr dev = NULL;
+    virPoolObjPtr obj = NULL;
     int ret = -1;
 
     if (VIR_ALLOC(def) < 0)
@@ -1420,17 +1430,18 @@ static int udevSetupSystemDev(void)
     udevGetDMIData(&def->caps->data);
 #endif
 
-    dev = virNodeDeviceAssignDef(&driver->devs, def);
-    if (dev == NULL)
+    if (!(obj = virPoolObjTableAdd(driver->devs, NULL, def->name,
+                                   def, NULL, NULL, virNodeDeviceDefFree,
+                                   NULL, 0)))
         goto cleanup;
+    def = NULL;
 
-    virNodeDeviceObjUnlock(dev);
+    virPoolObjEndAPI(&obj);
 
     ret = 0;
 
  cleanup:
-    if (ret == -1)
-        virNodeDeviceDefFree(def);
+    virNodeDeviceDefFree(def);
 
     return ret;
 }
@@ -1488,6 +1499,11 @@ static int nodeStateInitialize(bool privileged,
     nodeDeviceLock();
     driver->nodeDeviceEventState = virObjectEventStateNew();
 
+    if (!(driver->devs =
+          virPoolObjTableNew(VIR_POOLOBJTABLE_NODEDEVICE,
+                             VIR_POOLOBJTABLE_NODEDEVICE_HASHSTART, true)))
+        goto cleanup;
+
     if (udevPCITranslateInit(privileged) < 0)
         goto cleanup;
 
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 6820298..ce44728 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -36,6 +36,7 @@
 #include "virerror.h"
 #include "datatypes.h"
 #include "test_driver.h"
+#include "virpoolobj.h"
 #include "virbuffer.h"
 #include "viruuid.h"
 #include "capabilities.h"
@@ -51,6 +52,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"
@@ -98,7 +100,7 @@ struct _testDriver {
     bool transaction_running;
     virInterfaceObjList backupIfaces;
     virStoragePoolObjList pools;
-    virNodeDeviceObjList devs;
+    virPoolObjTablePtr devs;
     int numCells;
     testCell cells[MAX_CELLS];
     size_t numAuths;
@@ -149,7 +151,7 @@ testDriverFree(testDriverPtr driver)
     virObjectUnref(driver->caps);
     virObjectUnref(driver->xmlopt);
     virObjectUnref(driver->domains);
-    virNodeDeviceObjListFree(&driver->devs);
+    virObjectUnref(driver->devs);
     virObjectUnref(driver->networks);
     virInterfaceObjListFree(&driver->ifaces);
     virStoragePoolObjListFree(&driver->pools);
@@ -413,6 +415,9 @@ testDriverNew(void)
 
     if (!(ret->xmlopt = virDomainXMLOptionNew(NULL, NULL, &ns)) ||
         !(ret->eventState = virObjectEventStateNew()) ||
+        !(ret->devs = virPoolObjTableNew(VIR_POOLOBJTABLE_NODEDEVICE,
+                                         VIR_POOLOBJTABLE_NODEDEVICE_HASHSTART,
+                                         true)) ||
         !(ret->domains = virDomainObjListNew()) ||
         !(ret->networks = virNetworkObjListNew()))
         goto error;
@@ -1113,33 +1118,32 @@ testParseNodedevs(testDriverPtr privconn,
     int num, ret = -1;
     size_t i;
     xmlNodePtr *nodes = NULL;
-    virNodeDeviceObjPtr obj;
+    virNodeDeviceDefPtr def = NULL;
+    xmlNodePtr node;
+    virPoolObjPtr obj = NULL;
 
-    num = virXPathNodeSet("/node/device", ctxt, &nodes);
-    if (num < 0)
+    if ((num = virXPathNodeSet("/node/device", ctxt, &nodes)) < 0)
         goto error;
 
     for (i = 0; i < num; i++) {
-        virNodeDeviceDefPtr def;
-        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
-                                                  "nodedev");
-        if (!node)
+        if (!(node = testParseXMLDocFromFile(nodes[i], file, "nodedev")))
             goto error;
 
-        def = virNodeDeviceDefParseNode(ctxt->doc, node, 0, NULL);
-        if (!def)
+        if (!(def = virNodeDeviceDefParseNode(ctxt->doc, node, 0, NULL)))
             goto error;
 
-        if (!(obj = virNodeDeviceAssignDef(&privconn->devs, def))) {
-            virNodeDeviceDefFree(def);
+        if (!(obj = virPoolObjTableAdd(privconn->devs, NULL, def->name,
+                                       def, NULL, NULL, virNodeDeviceDefFree,
+                                       NULL, 0)))
             goto error;
-        }
+        def = NULL;
 
-        virNodeDeviceObjUnlock(obj);
+        virPoolObjEndAPI(&obj);
     }
 
     ret = 0;
  error:
+    virNodeDeviceDefFree(def);
     VIR_FREE(nodes);
     return ret;
 }
@@ -5374,27 +5378,34 @@ testStorageVolGetPath(virStorageVolPtr vol)
 
 /* Node device implementations */
 
+static virPoolObjPtr
+testNodeDeviceObjFindByName(virPoolObjTablePtr devobjs,
+                            const char *name)
+{
+    virPoolObjPtr obj;
+
+    if (!(obj = virPoolObjTableFindByName(devobjs, name)))
+        virReportError(VIR_ERR_NO_NODE_DEVICE,
+                       _("no node device with matching name '%s'"),
+                       name);
+
+    return obj;
+}
+
+
 static int
 testNodeNumOfDevices(virConnectPtr conn,
                      const char *cap,
                      unsigned int flags)
 {
     testDriverPtr driver = conn->privateData;
-    int ndevs = 0;
-    size_t i;
 
     virCheckFlags(0, -1);
 
-    testDriverLock(driver);
-    for (i = 0; i < driver->devs.count; i++)
-        if ((cap == NULL) ||
-            virNodeDeviceHasCap(driver->devs.objs[i], cap))
-            ++ndevs;
-    testDriverUnlock(driver);
-
-    return ndevs;
+    return virNodeDeviceObjNumOfDevices(driver->devs, conn, cap, NULL);
 }
 
+
 static int
 testNodeListDevices(virConnectPtr conn,
                     const char *cap,
@@ -5403,118 +5414,73 @@ testNodeListDevices(virConnectPtr conn,
                     unsigned int flags)
 {
     testDriverPtr driver = conn->privateData;
-    int ndevs = 0;
-    size_t i;
 
     virCheckFlags(0, -1);
 
-    testDriverLock(driver);
-    for (i = 0; i < driver->devs.count && ndevs < maxnames; i++) {
-        virNodeDeviceObjLock(driver->devs.objs[i]);
-        if (cap == NULL ||
-            virNodeDeviceHasCap(driver->devs.objs[i], cap)) {
-            if (VIR_STRDUP(names[ndevs++], driver->devs.objs[i]->def->name) < 0) {
-                virNodeDeviceObjUnlock(driver->devs.objs[i]);
-                goto failure;
-            }
-        }
-        virNodeDeviceObjUnlock(driver->devs.objs[i]);
-    }
-    testDriverUnlock(driver);
-
-    return ndevs;
-
- failure:
-    testDriverUnlock(driver);
-    --ndevs;
-    while (--ndevs >= 0)
-        VIR_FREE(names[ndevs]);
-    return -1;
+    return virNodeDeviceObjGetNames(driver->devs, conn, NULL,
+                                    cap, names, maxnames);
 }
 
+
 static virNodeDevicePtr
 testNodeDeviceLookupByName(virConnectPtr conn, const char *name)
 {
     testDriverPtr driver = conn->privateData;
-    virNodeDeviceObjPtr obj;
+    virPoolObjPtr obj;
     virNodeDevicePtr ret = NULL;
 
-    testDriverLock(driver);
-    obj = virNodeDeviceFindByName(&driver->devs, name);
-    testDriverUnlock(driver);
-
-    if (!obj) {
-        virReportError(VIR_ERR_NO_NODE_DEVICE,
-                       _("no node device with matching name '%s'"),
-                       name);
-        goto cleanup;
-    }
+    if (!(obj = testNodeDeviceObjFindByName(driver->devs, name)))
+        return NULL;
 
     ret = virGetNodeDevice(conn, name);
 
- cleanup:
-    if (obj)
-        virNodeDeviceObjUnlock(obj);
+    virPoolObjEndAPI(&obj);
     return ret;
 }
 
+
 static char *
 testNodeDeviceGetXMLDesc(virNodeDevicePtr dev,
                          unsigned int flags)
 {
     testDriverPtr driver = dev->conn->privateData;
-    virNodeDeviceObjPtr obj;
+    virPoolObjPtr obj;
+    virNodeDeviceDefPtr def;
     char *ret = NULL;
 
     virCheckFlags(0, NULL);
 
-    testDriverLock(driver);
-    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
-    testDriverUnlock(driver);
-
-    if (!obj) {
-        virReportError(VIR_ERR_NO_NODE_DEVICE,
-                       _("no node device with matching name '%s'"),
-                       dev->name);
-        goto cleanup;
-    }
+    if (!(obj = testNodeDeviceObjFindByName(driver->devs, dev->name)))
+        return NULL;
+    def = virPoolObjGetDef(obj);
 
-    ret = virNodeDeviceDefFormat(obj->def);
+    ret = virNodeDeviceDefFormat(def);
 
- cleanup:
-    if (obj)
-        virNodeDeviceObjUnlock(obj);
+    virPoolObjEndAPI(&obj);
     return ret;
 }
 
+
 static char *
 testNodeDeviceGetParent(virNodeDevicePtr dev)
 {
     testDriverPtr driver = dev->conn->privateData;
-    virNodeDeviceObjPtr obj;
+    virPoolObjPtr obj;
+    virNodeDeviceDefPtr def;
     char *ret = NULL;
 
-    testDriverLock(driver);
-    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
-    testDriverUnlock(driver);
-
-    if (!obj) {
-        virReportError(VIR_ERR_NO_NODE_DEVICE,
-                       _("no node device with matching name '%s'"),
-                       dev->name);
-        goto cleanup;
-    }
+    if (!(obj = testNodeDeviceObjFindByName(driver->devs, dev->name)))
+        return NULL;
+    def = virPoolObjGetDef(obj);
 
-    if (obj->def->parent) {
-        ignore_value(VIR_STRDUP(ret, obj->def->parent));
+    if (def->parent) {
+        ignore_value(VIR_STRDUP(ret, def->parent));
     } else {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("no parent for this device"));
     }
 
- cleanup:
-    if (obj)
-        virNodeDeviceObjUnlock(obj);
+    virPoolObjEndAPI(&obj);
     return ret;
 }
 
@@ -5523,30 +5489,20 @@ static int
 testNodeDeviceNumOfCaps(virNodeDevicePtr dev)
 {
     testDriverPtr driver = dev->conn->privateData;
-    virNodeDeviceObjPtr obj;
+    virPoolObjPtr obj;
+    virNodeDeviceDefPtr def;
     virNodeDevCapsDefPtr caps;
     int ncaps = 0;
-    int ret = -1;
-
-    testDriverLock(driver);
-    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
-    testDriverUnlock(driver);
 
-    if (!obj) {
-        virReportError(VIR_ERR_NO_NODE_DEVICE,
-                       _("no node device with matching name '%s'"),
-                       dev->name);
-        goto cleanup;
-    }
+    if (!(obj = testNodeDeviceObjFindByName(driver->devs, dev->name)))
+        return -1;
+    def = virPoolObjGetDef(obj);
 
-    for (caps = obj->def->caps; caps; caps = caps->next)
+    for (caps = def->caps; caps; caps = caps->next)
         ++ncaps;
-    ret = ncaps;
 
- cleanup:
-    if (obj)
-        virNodeDeviceObjUnlock(obj);
-    return ret;
+    virPoolObjEndAPI(&obj);
+    return ncaps;
 }
 
 
@@ -5554,31 +5510,25 @@ static int
 testNodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames)
 {
     testDriverPtr driver = dev->conn->privateData;
-    virNodeDeviceObjPtr obj;
+    virPoolObjPtr obj;
+    virNodeDeviceDefPtr def;
     virNodeDevCapsDefPtr caps;
     int ncaps = 0;
     int ret = -1;
 
-    testDriverLock(driver);
-    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
-    testDriverUnlock(driver);
-
-    if (!obj) {
-        virReportError(VIR_ERR_NO_NODE_DEVICE,
-                       _("no node device with matching name '%s'"),
-                       dev->name);
-        goto cleanup;
-    }
+    if (!(obj = testNodeDeviceObjFindByName(driver->devs, dev->name)))
+        return -1;
+    def = virPoolObjGetDef(obj);
 
-    for (caps = obj->def->caps; caps && ncaps < maxnames; caps = caps->next) {
-        if (VIR_STRDUP(names[ncaps++], virNodeDevCapTypeToString(caps->data.type)) < 0)
+    for (caps = def->caps; caps && ncaps < maxnames; caps = caps->next) {
+        if (VIR_STRDUP(names[ncaps++],
+                       virNodeDevCapTypeToString(caps->data.type)) < 0)
             goto cleanup;
     }
     ret = ncaps;
 
  cleanup:
-    if (obj)
-        virNodeDeviceObjUnlock(obj);
+    virPoolObjEndAPI(&obj);
     if (ret == -1) {
         --ncaps;
         while (--ncaps >= 0)
@@ -5587,6 +5537,7 @@ testNodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames)
     return ret;
 }
 
+
 static virNodeDevicePtr
 testNodeDeviceCreateXML(virConnectPtr conn,
                         const char *xmlDesc,
@@ -5594,7 +5545,8 @@ testNodeDeviceCreateXML(virConnectPtr conn,
 {
     testDriverPtr driver = conn->privateData;
     virNodeDeviceDefPtr def = NULL;
-    virNodeDeviceObjPtr obj = NULL;
+    virPoolObjPtr obj = NULL;
+    virNodeDeviceDefPtr objdef;
     char *wwnn = NULL, *wwpn = NULL;
     int parent_host = -1;
     virNodeDevicePtr dev = NULL;
@@ -5603,20 +5555,17 @@ testNodeDeviceCreateXML(virConnectPtr conn,
 
     virCheckFlags(0, NULL);
 
-    testDriverLock(driver);
-
-    def = virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE, NULL);
-    if (def == NULL)
+    if (!(def = virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE, NULL)))
         goto cleanup;
 
     /* We run these next two simply for validation */
     if (virNodeDeviceGetWWNs(def, &wwnn, &wwpn) == -1)
         goto cleanup;
 
-    if (virNodeDeviceGetParentHost(&driver->devs,
-                                   def->name,
-                                   def->parent,
-                                   &parent_host) == -1) {
+    if (virNodeDeviceObjGetParentHost(driver->devs,
+                                      def->name,
+                                      def->parent,
+                                      &parent_host) == -1) {
         goto cleanup;
     }
 
@@ -5638,19 +5587,20 @@ testNodeDeviceCreateXML(virConnectPtr conn,
         caps = caps->next;
     }
 
-
-    if (!(obj = virNodeDeviceAssignDef(&driver->devs, def)))
+    if (!(obj = virPoolObjTableAdd(driver->devs, NULL, def->name,
+                                   def, NULL, NULL, virNodeDeviceDefFree,
+                                   NULL, 0)))
         goto cleanup;
-    virNodeDeviceObjUnlock(obj);
+    VIR_STEAL_PTR(objdef, def);
 
-    event = virNodeDeviceEventLifecycleNew(def->name,
+    event = virNodeDeviceEventLifecycleNew(objdef->name,
                                            VIR_NODE_DEVICE_EVENT_CREATED,
                                            0);
 
-    dev = virGetNodeDevice(conn, def->name);
-    def = NULL;
+    dev = virGetNodeDevice(conn, objdef->name);
+
  cleanup:
-    testDriverUnlock(driver);
+    virPoolObjEndAPI(&obj);
     virNodeDeviceDefFree(def);
     testObjectEventQueue(driver, event);
     VIR_FREE(wwnn);
@@ -5658,60 +5608,44 @@ testNodeDeviceCreateXML(virConnectPtr conn,
     return dev;
 }
 
+
 static int
 testNodeDeviceDestroy(virNodeDevicePtr dev)
 {
-    int ret = 0;
+    int ret = -1;
     testDriverPtr driver = dev->conn->privateData;
-    virNodeDeviceObjPtr obj = NULL;
-    char *parent_name = NULL, *wwnn = NULL, *wwpn = NULL;
+    virPoolObjPtr obj = NULL;
+    virNodeDeviceDefPtr def;
+    char *wwnn = NULL;
+    char *wwpn = NULL;
     int parent_host = -1;
     virObjectEventPtr event = NULL;
 
-    testDriverLock(driver);
-    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
-    testDriverUnlock(driver);
-
-    if (!obj) {
-        virReportError(VIR_ERR_NO_NODE_DEVICE,
-                       _("no node device with matching name '%s'"),
-                       dev->name);
-        goto out;
-    }
-
-    if (virNodeDeviceGetWWNs(obj->def, &wwnn, &wwpn) == -1)
-        goto out;
-
-    if (VIR_STRDUP(parent_name, obj->def->parent) < 0)
-        goto out;
+    if (!(obj = testNodeDeviceObjFindByName(driver->devs, dev->name)))
+        return -1;
+    def = virPoolObjGetDef(obj);
 
-    /* virNodeDeviceGetParentHost will cause the device object's lock to be
-     * taken, so we have to dup the parent's name and drop the lock
-     * before calling it.  We don't need the reference to the object
-     * any more once we have the parent's name.  */
-    virNodeDeviceObjUnlock(obj);
+    if (virNodeDeviceGetWWNs(def, &wwnn, &wwpn) == -1)
+        goto cleanup;
 
     /* We do this just for basic validation */
-    if (virNodeDeviceGetParentHost(&driver->devs,
-                                   dev->name,
-                                   parent_name,
-                                   &parent_host) == -1) {
-        obj = NULL;
-        goto out;
-    }
+    if (virNodeDeviceObjGetParentHost(driver->devs,
+                                      dev->name,
+                                      def->parent,
+                                      &parent_host) == -1)
+        goto cleanup;
 
     event = virNodeDeviceEventLifecycleNew(dev->name,
                                            VIR_NODE_DEVICE_EVENT_DELETED,
                                            0);
 
-    virNodeDeviceObjLock(obj);
-    virNodeDeviceObjRemove(&driver->devs, &obj);
+    virPoolObjTableRemove(driver->devs, &obj);
 
- out:
-    if (obj)
-        virNodeDeviceObjUnlock(obj);
+    ret = 0;
+
+ cleanup:
+    virPoolObjEndAPI(&obj);
     testObjectEventQueue(driver, event);
-    VIR_FREE(parent_name);
     VIR_FREE(wwnn);
     VIR_FREE(wwpn);
     return ret;
-- 
2.7.4




More information about the libvir-list mailing list