[libvirt] [PATCH RFC 7/9] volume: Convert virStorageVolObj[List] to use virPoolObj[Table]

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


Use the virPoolObj[Table] object management model in order to manage the
storage volume 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.

Signed-off-by: John Ferlan <jferlan at redhat.com>
---
 src/conf/storage_conf.c                | 205 +++++++++++--
 src/conf/storage_conf.h                |  45 ++-
 src/libvirt_private.syms               |  10 +-
 src/storage/storage_backend_disk.c     | 143 ++++++---
 src/storage/storage_backend_gluster.c  |  17 +-
 src/storage/storage_backend_logical.c  |  58 ++--
 src/storage/storage_backend_mpath.c    |  10 +-
 src/storage/storage_backend_rbd.c      |  10 +-
 src/storage/storage_backend_sheepdog.c |   7 +-
 src/storage/storage_backend_zfs.c      |  51 ++--
 src/storage/storage_driver.c           | 539 ++++++++++++++++++---------------
 src/storage/storage_util.c             |  10 +-
 src/test/test_driver.c                 | 371 ++++++++++++-----------
 13 files changed, 875 insertions(+), 601 deletions(-)

diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
index c9b93aa..8012b6f 100644
--- a/src/conf/storage_conf.c
+++ b/src/conf/storage_conf.c
@@ -321,8 +321,9 @@ virStorageVolOptionsForPoolType(int type)
 
 
 void
-virStorageVolDefFree(virStorageVolDefPtr def)
+virStorageVolDefFree(void *opaque)
 {
+    virStorageVolDefPtr def = opaque;
     size_t i;
 
     if (!def)
@@ -415,7 +416,7 @@ virStoragePoolObjFree(virStoragePoolObjPtr obj)
     if (!obj)
         return;
 
-    virStoragePoolObjClearVols(obj);
+    virObjectUnref(obj->volumes);
 
     virStoragePoolDefFree(obj->def);
     virStoragePoolDefFree(obj->newDef);
@@ -1776,56 +1777,74 @@ virStoragePoolSourceFindDuplicateDevices(virStoragePoolObjPtr pool,
     return NULL;
 }
 
+
 void
 virStoragePoolObjClearVols(virStoragePoolObjPtr pool)
 {
-    size_t i;
-    for (i = 0; i < pool->volumes.count; i++)
-        virStorageVolDefFree(pool->volumes.objs[i]);
+    virPoolObjTableClearAll(pool->volumes);
+}
+
+
+struct volSearchData {
+    const char *compare;
+};
 
-    VIR_FREE(pool->volumes.objs);
-    pool->volumes.count = 0;
+static bool
+volFindByKey(virPoolObjPtr obj,
+             void *opaque)
+{
+    virStorageVolDefPtr def = virPoolObjGetDef(obj);
+    struct volSearchData *data = opaque;
+
+    if (STREQ(def->key, data->compare))
+        return true;
+
+    return false;
 }
 
-virStorageVolDefPtr
-virStorageVolDefFindByKey(virStoragePoolObjPtr pool,
+
+virPoolObjPtr
+virStorageVolObjFindByKey(virStoragePoolObjPtr pool,
                           const char *key)
 {
-    size_t i;
+    struct volSearchData data = { .compare = key };
 
-    for (i = 0; i < pool->volumes.count; i++)
-        if (STREQ(pool->volumes.objs[i]->key, key))
-            return pool->volumes.objs[i];
-
-    return NULL;
+    return virPoolObjTableSearchRef(pool->volumes, volFindByKey, &data);
 }
 
-virStorageVolDefPtr
-virStorageVolDefFindByPath(virStoragePoolObjPtr pool,
-                           const char *path)
+
+static bool
+volFindByPath(virPoolObjPtr obj,
+              void *opaque)
 {
-    size_t i;
+    virStorageVolDefPtr def = virPoolObjGetDef(obj);
+    struct volSearchData *data = opaque;
 
-    for (i = 0; i < pool->volumes.count; i++)
-        if (STREQ(pool->volumes.objs[i]->target.path, path))
-            return pool->volumes.objs[i];
+    if (STREQ(def->target.path, data->compare))
+        return true;
 
-    return NULL;
+    return false;
 }
 
-virStorageVolDefPtr
-virStorageVolDefFindByName(virStoragePoolObjPtr pool,
-                           const char *name)
+
+virPoolObjPtr
+virStorageVolObjFindByPath(virStoragePoolObjPtr pool,
+                           const char *path)
 {
-    size_t i;
+    struct volSearchData data = { .compare = path };
 
-    for (i = 0; i < pool->volumes.count; i++)
-        if (STREQ(pool->volumes.objs[i]->name, name))
-            return pool->volumes.objs[i];
+    return virPoolObjTableSearchRef(pool->volumes, volFindByPath, &data);
+}
 
-    return NULL;
+
+virPoolObjPtr
+virStorageVolObjFindByName(virStoragePoolObjPtr pool,
+                           const char *name)
+{
+    return virPoolObjTableFindByName(pool->volumes, name);
 }
 
+
 virStoragePoolObjPtr
 virStoragePoolObjAssignDef(virStoragePoolObjListPtr pools,
                            virStoragePoolDefPtr def)
@@ -1855,6 +1874,14 @@ virStoragePoolObjAssignDef(virStoragePoolObjListPtr pools,
     virStoragePoolObjLock(pool);
     pool->active = 0;
 
+    if (!(pool->volumes =
+          virPoolObjTableNew(VIR_POOLOBJTABLE_VOLUME,
+                             VIR_POOLOBJTABLE_VOLUME_HASHSTART, true))) {
+        virStoragePoolObjUnlock(pool);
+        virStoragePoolObjFree(pool);
+        return NULL;
+    }
+
     if (VIR_APPEND_ELEMENT_COPY(pools->objs, pools->count, pool) < 0) {
         virStoragePoolObjUnlock(pool);
         virStoragePoolObjFree(pool);
@@ -1865,6 +1892,122 @@ virStoragePoolObjAssignDef(virStoragePoolObjListPtr pools,
     return pool;
 }
 
+
+virPoolObjPtr
+virStoragePoolObjAddVolume(virStoragePoolObjPtr pool,
+                           virStorageVolDefPtr voldef)
+{
+    return virPoolObjTableAdd(pool->volumes, NULL, voldef->name, voldef,
+                              NULL, NULL, virStorageVolDefFree, NULL, 0);
+}
+
+
+void
+virStoragePoolObjRemoveVolume(virStoragePoolObjPtr pool,
+                              virPoolObjPtr *volobj)
+{
+    virPoolObjTableRemove(pool->volumes, volobj);
+}
+
+
+struct volCountData {
+    virConnectPtr conn;
+    virStoragePoolDefPtr pooldef;
+    virStoragePoolVolumeACLFilter aclfilter;
+    int count;
+};
+
+static int
+volCount(virPoolObjPtr obj,
+         void *opaque)
+{
+    struct volCountData *data = opaque;
+
+    /* Similar to virPoolObjTableListIterator */
+    if (data->aclfilter && !data->aclfilter(data->conn, data->pooldef, obj))
+        return 0;
+
+    data->count++;
+    return 0;
+}
+
+
+int
+virStoragePoolObjNumOfVolumes(virPoolObjTablePtr volumes,
+                              virConnectPtr conn,
+                              virStoragePoolDefPtr pooldef,
+                              virStoragePoolVolumeACLFilter aclfilter)
+{
+    struct volCountData data = { .conn = conn,
+                                 .count = 0,
+                                 .pooldef = pooldef,
+                                 .aclfilter = aclfilter };
+
+    if (virPoolObjTableList(volumes, conn, NULL, volCount, &data) < 0)
+        return 0;
+
+    return data.count;
+}
+
+
+struct volListData {
+    virConnectPtr conn;
+    virStoragePoolDefPtr pooldef;
+    virStoragePoolVolumeACLFilter aclfilter;
+    int nnames;
+    char **const names;
+    int maxnames;
+};
+
+static int
+volListVolumes(virPoolObjPtr obj,
+               void *opaque)
+{
+    virStorageVolDefPtr def = virPoolObjGetDef(obj);
+    struct volListData *data = opaque;
+
+    /* Similar to virPoolObjTableListIterator */
+    if (data->aclfilter && !data->aclfilter(data->conn, data->pooldef, obj))
+        return 0;
+
+    if (data->nnames < data->maxnames) {
+        if (VIR_STRDUP(data->names[data->nnames++], def->name) < 0)
+            return -1;
+    }
+
+    return 0;
+}
+
+
+int
+virStoragePoolObjListVolumes(virPoolObjTablePtr volumes,
+                             virConnectPtr conn,
+                             virStoragePoolDefPtr pooldef,
+                             virStoragePoolVolumeACLFilter aclfilter,
+                             char **const names,
+                             int maxnames)
+{
+    struct volListData data = { .conn = conn,
+                                .nnames = 0,
+                                .pooldef = pooldef,
+                                .aclfilter = aclfilter,
+                                .names = names,
+                                .maxnames = maxnames };
+
+    memset(names, 0, maxnames * sizeof(*names));
+
+    if (virPoolObjTableList(volumes, conn, NULL, volListVolumes, &data) < 0)
+        goto error;
+
+    return data.nnames;
+
+ error:
+    while (--data.nnames >= 0)
+        VIR_FREE(names[data.nnames]);
+    return -1;
+}
+
+
 static virStoragePoolObjPtr
 virStoragePoolObjLoad(virStoragePoolObjListPtr pools,
                       const char *file,
diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h
index 5eda544..cfc8281 100644
--- a/src/conf/storage_conf.h
+++ b/src/conf/storage_conf.h
@@ -28,6 +28,7 @@
 # include "virstorageencryption.h"
 # include "virstoragefile.h"
 # include "virbitmap.h"
+# include "virpoolobj.h"
 # include "virthread.h"
 # include "device_conf.h"
 # include "node_device_conf.h"
@@ -73,13 +74,6 @@ struct _virStorageVolDef {
     virStorageSource target;
 };
 
-typedef struct _virStorageVolDefList virStorageVolDefList;
-typedef virStorageVolDefList *virStorageVolDefListPtr;
-struct _virStorageVolDefList {
-    size_t count;
-    virStorageVolDefPtr *objs;
-};
-
 VIR_ENUM_DECL(virStorageVol)
 
 typedef enum {
@@ -279,7 +273,7 @@ struct _virStoragePoolObj {
     virStoragePoolDefPtr def;
     virStoragePoolDefPtr newDef;
 
-    virStorageVolDefList volumes;
+    virPoolObjTablePtr volumes;
 };
 
 typedef struct _virStoragePoolObjList virStoragePoolObjList;
@@ -343,14 +337,14 @@ virStoragePoolObjPtr
 virStoragePoolSourceFindDuplicateDevices(virStoragePoolObjPtr pool,
                                          virStoragePoolDefPtr def);
 
-virStorageVolDefPtr
-virStorageVolDefFindByKey(virStoragePoolObjPtr pool,
+virPoolObjPtr
+virStorageVolObjFindByKey(virStoragePoolObjPtr pool,
                           const char *key);
-virStorageVolDefPtr
-virStorageVolDefFindByPath(virStoragePoolObjPtr pool,
+virPoolObjPtr
+virStorageVolObjFindByPath(virStoragePoolObjPtr pool,
                            const char *path);
-virStorageVolDefPtr
-virStorageVolDefFindByName(virStoragePoolObjPtr pool,
+virPoolObjPtr
+virStorageVolObjFindByName(virStoragePoolObjPtr pool,
                            const char *name);
 
 void virStoragePoolObjClearVols(virStoragePoolObjPtr pool);
@@ -387,6 +381,27 @@ virStoragePoolObjPtr
 virStoragePoolObjAssignDef(virStoragePoolObjListPtr pools,
                            virStoragePoolDefPtr def);
 
+virPoolObjPtr virStoragePoolObjAddVolume(virStoragePoolObjPtr pool,
+                                         virStorageVolDefPtr voldef);
+
+void virStoragePoolObjRemoveVolume(virStoragePoolObjPtr pool,
+                                   virPoolObjPtr *volobj);
+
+typedef bool (*virStoragePoolVolumeACLFilter)
+    (virConnectPtr conn, virStoragePoolDefPtr pool, void *objdef);
+
+int virStoragePoolObjNumOfVolumes(virPoolObjTablePtr volumes,
+                                  virConnectPtr conn,
+                                  virStoragePoolDefPtr pooldef,
+                                  virStoragePoolVolumeACLFilter aclfilter);
+
+int virStoragePoolObjListVolumes(virPoolObjTablePtr volumes,
+                                 virConnectPtr conn,
+                                 virStoragePoolDefPtr pooldef,
+                                 virStoragePoolVolumeACLFilter aclfilter,
+                                 char **const names,
+                                 int maxnames);
+
 int virStoragePoolSaveState(const char *stateFile,
                             virStoragePoolDefPtr def);
 int virStoragePoolSaveConfig(const char *configFile,
@@ -396,7 +411,7 @@ int virStoragePoolObjSaveDef(virStorageDriverStatePtr driver,
                              virStoragePoolDefPtr def);
 int virStoragePoolObjDeleteDef(virStoragePoolObjPtr pool);
 
-void virStorageVolDefFree(virStorageVolDefPtr def);
+void virStorageVolDefFree(void *opaque);
 void virStoragePoolSourceClear(virStoragePoolSourcePtr source);
 void virStoragePoolSourceDeviceClear(virStoragePoolSourceDevicePtr dev);
 void virStoragePoolSourceFree(virStoragePoolSourcePtr source);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 17de708..14c3682 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -862,6 +862,7 @@ virStoragePoolFormatLogicalTypeToString;
 virStoragePoolGetVhbaSCSIHostParent;
 virStoragePoolLoadAllConfigs;
 virStoragePoolLoadAllState;
+virStoragePoolObjAddVolume;
 virStoragePoolObjAssignDef;
 virStoragePoolObjClearVols;
 virStoragePoolObjDeleteDef;
@@ -870,8 +871,11 @@ virStoragePoolObjFindByUUID;
 virStoragePoolObjIsDuplicate;
 virStoragePoolObjListExport;
 virStoragePoolObjListFree;
+virStoragePoolObjListVolumes;
 virStoragePoolObjLock;
+virStoragePoolObjNumOfVolumes;
 virStoragePoolObjRemove;
+virStoragePoolObjRemoveVolume;
 virStoragePoolObjSaveDef;
 virStoragePoolObjUnlock;
 virStoragePoolSaveConfig;
@@ -887,14 +891,14 @@ virStoragePoolSourceListFormat;
 virStoragePoolSourceListNewSource;
 virStoragePoolTypeFromString;
 virStoragePoolTypeToString;
-virStorageVolDefFindByKey;
-virStorageVolDefFindByName;
-virStorageVolDefFindByPath;
 virStorageVolDefFormat;
 virStorageVolDefFree;
 virStorageVolDefParseFile;
 virStorageVolDefParseNode;
 virStorageVolDefParseString;
+virStorageVolObjFindByKey;
+virStorageVolObjFindByName;
+virStorageVolObjFindByPath;
 virStorageVolTypeFromString;
 virStorageVolTypeToString;
 
diff --git a/src/storage/storage_backend_disk.c b/src/storage/storage_backend_disk.c
index 819f1e5..dcf4e3e 100644
--- a/src/storage/storage_backend_disk.c
+++ b/src/storage/storage_backend_disk.c
@@ -43,6 +43,20 @@ VIR_LOG_INIT("storage.storage_backend_disk");
 
 #define SECTOR_SIZE 512
 
+
+static bool
+volPartFindExtended(virPoolObjPtr volobj,
+                    void *opaque ATTRIBUTE_UNUSED)
+{
+    virStorageVolDefPtr def = virPoolObjGetDef(volobj);
+
+    if (def->source.partType == VIR_STORAGE_VOL_DISK_TYPE_EXTENDED)
+        return true;
+
+    return false;
+}
+
+
 static int
 virStorageBackendDiskMakeDataVol(virStoragePoolObjPtr pool,
                                  char **const groups,
@@ -59,17 +73,21 @@ virStorageBackendDiskMakeDataVol(virStoragePoolObjPtr pool,
         partname = groups[0];
 
     if (vol == NULL) {
+        virPoolObjPtr volobj;
         /* This is typically a reload/restart/refresh path where
          * we're discovering the existing partitions for the pool
          */
-        if (VIR_ALLOC(vol) < 0)
+        if (VIR_ALLOC(vol) < 0 ||
+            VIR_STRDUP(vol->name, partname) < 0) {
+            VIR_FREE(vol);
             return -1;
-        if (VIR_STRDUP(vol->name, partname) < 0 ||
-            VIR_APPEND_ELEMENT_COPY(pool->volumes.objs,
-                                    pool->volumes.count, vol) < 0) {
+        }
+
+        if (!(volobj = virStoragePoolObjAddVolume(pool, vol))) {
             virStorageVolDefFree(vol);
             return -1;
         }
+        virPoolObjEndAPI(&volobj);
     }
 
     if (vol->target.path == NULL) {
@@ -192,15 +210,13 @@ virStorageBackendDiskMakeDataVol(virStoragePoolObjPtr pool,
 
     /* Find the extended partition and increase the allocation value */
     if (vol->source.partType == VIR_STORAGE_VOL_DISK_TYPE_LOGICAL) {
-        size_t i;
+        virPoolObjPtr volobj;
 
-        for (i = 0; i < pool->volumes.count; i++) {
-            if (pool->volumes.objs[i]->source.partType ==
-                VIR_STORAGE_VOL_DISK_TYPE_EXTENDED) {
-                pool->volumes.objs[i]->target.allocation +=
-                    vol->target.allocation;
-                break;
-            }
+        if ((volobj = virPoolObjTableSearch(pool->volumes, volPartFindExtended,
+                                            NULL))) {
+            virStorageVolDefPtr voldef = virPoolObjGetDef(volobj);
+            voldef->target.allocation += vol->target.allocation;
+            virPoolObjEndAPI(&volobj);
         }
     }
 
@@ -285,21 +301,26 @@ virStorageBackendDiskMakeVol(size_t ntok ATTRIBUTE_UNUSED,
     /* Remaining data / metadata parts get turn into volumes... */
     if (STREQ(groups[2], "metadata") ||
         STREQ(groups[2], "data")) {
-        virStorageVolDefPtr vol = data->vol;
+        virStorageVolDefPtr voldef = data->vol;
 
-        if (vol) {
+        if (voldef) {
             /* We're searching for a specific vol only */
-            if (vol->key) {
-                if (STRNEQ(vol->key, groups[0]))
+            if (voldef->key) {
+                if (STRNEQ(voldef->key, groups[0]))
+                    return 0;
+            } else {
+                virPoolObjPtr volobj;
+
+                if ((volobj = virStorageVolObjFindByKey(pool, groups[0]))) {
+                    /* If no key, the volume must be newly created. If groups[0]
+                     * isn't already a volume, assume it's the path we want */
+                    virPoolObjEndAPI(&volobj);
                     return 0;
-            } else if (virStorageVolDefFindByKey(pool, groups[0]) != NULL) {
-                /* If no key, the volume must be newly created. If groups[0]
-                 * isn't already a volume, assume it's the path we want */
-                return 0;
+                }
             }
         }
 
-        return virStorageBackendDiskMakeDataVol(pool, groups, vol);
+        return virStorageBackendDiskMakeDataVol(pool, groups, voldef);
     } else if (STREQ(groups[2], "free")) {
         /* ....or free space extents */
         return virStorageBackendDiskMakeFreeExtent(pool, groups);
@@ -518,6 +539,28 @@ virStorageBackendDiskBuildPool(virConnectPtr conn ATTRIBUTE_UNUSED,
     return ret;
 }
 
+
+struct volPartListData {
+    int count;
+};
+
+
+static int
+volNumOfPartTypes(virPoolObjPtr volobj,
+                  void *opaque)
+{
+    virStorageVolDefPtr def = virPoolObjGetDef(volobj);
+    struct volPartListData *data = opaque;
+    int partType = def->source.partType;
+
+    if (partType == VIR_STORAGE_VOL_DISK_TYPE_PRIMARY ||
+        partType == VIR_STORAGE_VOL_DISK_TYPE_EXTENDED)
+        data->count++;
+
+    return 0;
+}
+
+
 /**
  * Decides what kind of partition type that should be created.
  * Important when the partition table is of msdos type
@@ -525,19 +568,17 @@ virStorageBackendDiskBuildPool(virConnectPtr conn ATTRIBUTE_UNUSED,
 static int
 virStorageBackendDiskPartTypeToCreate(virStoragePoolObjPtr pool)
 {
+    struct volPartListData data = { .count = 0 };
+
     if (pool->def->source.format == VIR_STORAGE_POOL_DISK_DOS) {
+
         /* count primary and extended partitions,
-           can't be more than 3 to create a new primary partition */
-        size_t i;
-        int count = 0;
-        for (i = 0; i < pool->volumes.count; i++) {
-            int partType = pool->volumes.objs[i]->source.partType;
-            if (partType == VIR_STORAGE_VOL_DISK_TYPE_PRIMARY ||
-                partType == VIR_STORAGE_VOL_DISK_TYPE_EXTENDED)
-                count++;
+         * can't be more than 3 to create a new primary partition */
+        if (virPoolObjTableList(pool->volumes, NULL, NULL,
+                                volNumOfPartTypes, &data) == 0) {
+            if (data.count >= 4)
+                return VIR_STORAGE_VOL_DISK_TYPE_LOGICAL;
         }
-        if (count >= 4)
-            return VIR_STORAGE_VOL_DISK_TYPE_LOGICAL;
     }
 
     /* for all other cases, all partitions are primary */
@@ -549,7 +590,8 @@ virStorageBackendDiskPartFormat(virStoragePoolObjPtr pool,
                                 virStorageVolDefPtr vol,
                                 char** partFormat)
 {
-    size_t i;
+    virPoolObjPtr volobj;
+
     if (pool->def->source.format == VIR_STORAGE_POOL_DISK_DOS) {
         const char *partedFormat;
         partedFormat = virStoragePartedFsTypeToString(vol->target.format);
@@ -560,14 +602,14 @@ virStorageBackendDiskPartFormat(virStoragePoolObjPtr pool,
         }
         if (vol->target.format == VIR_STORAGE_VOL_DISK_EXTENDED) {
             /* make sure we don't have an extended partition already */
-            for (i = 0; i < pool->volumes.count; i++) {
-                if (pool->volumes.objs[i]->source.partType ==
-                    VIR_STORAGE_VOL_DISK_TYPE_EXTENDED) {
-                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                                   _("extended partition already exists"));
-                    return -1;
-                }
+            if ((volobj == virPoolObjTableSearch(pool->volumes,
+                                                 volPartFindExtended, NULL))) {
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("extended partition already exists"));
+                virPoolObjEndAPI(&volobj);
+                return -1;
             }
+
             if (VIR_STRDUP(*partFormat, partedFormat) < 0)
                 return -1;
         } else {
@@ -582,18 +624,19 @@ virStorageBackendDiskPartFormat(virStoragePoolObjPtr pool,
                 break;
             case VIR_STORAGE_VOL_DISK_TYPE_LOGICAL:
                 /* make sure we have an extended partition */
-                for (i = 0; i < pool->volumes.count; i++) {
-                    if (pool->volumes.objs[i]->source.partType ==
-                        VIR_STORAGE_VOL_DISK_TYPE_EXTENDED) {
-                        if (virAsprintf(partFormat, "logical %s",
-                                        partedFormat) < 0)
-                            return -1;
-                        break;
+                if ((volobj == virPoolObjTableSearch(pool->volumes,
+                                                     volPartFindExtended,
+                                                     NULL))) {
+                    if (virAsprintf(partFormat, "logical %s",
+                                    partedFormat) < 0) {
+                        virPoolObjEndAPI(&volobj);
+                        return -1;
                     }
-                }
-                if (i == pool->volumes.count) {
-                    virReportError(VIR_ERR_INTERNAL_ERROR,
-                                   "%s", _("no extended partition found and no primary partition available"));
+                    virPoolObjEndAPI(&volobj);
+                } else {
+                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                                   _("no extended partition found and no "
+                                     "primary partition available"));
                     return -1;
                 }
                 break;
diff --git a/src/storage/storage_backend_gluster.c b/src/storage/storage_backend_gluster.c
index 7be2d9e..aa9d7be 100644
--- a/src/storage/storage_backend_gluster.c
+++ b/src/storage/storage_backend_gluster.c
@@ -379,15 +379,20 @@ virStorageBackendGlusterRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED,
     }
     while (!(errno = glfs_readdirplus_r(dir, &st, &de.ent, &ent)) && ent) {
         virStorageVolDefPtr vol;
-        int okay = virStorageBackendGlusterRefreshVol(state,
-                                                      ent->d_name, &st,
-                                                      &vol);
+        virPoolObjPtr volobj;
 
-        if (okay < 0)
+        if (virStorageBackendGlusterRefreshVol(state, ent->d_name,
+                                               &st, &vol) < 0)
             goto cleanup;
-        if (vol && VIR_APPEND_ELEMENT(pool->volumes.objs, pool->volumes.count,
-                                      vol) < 0)
+
+        if (!vol)
+            continue;
+
+        if (!(volobj = virStoragePoolObjAddVolume(pool, vol))) {
+            virStorageVolDefFree(vol);
             goto cleanup;
+        }
+        virPoolObjEndAPI(&volobj);
     }
     if (errno) {
         virReportSystemError(errno, _("failed to read directory '%s' in '%s'"),
diff --git a/src/storage/storage_backend_logical.c b/src/storage/storage_backend_logical.c
index b0191aa..ad66656 100644
--- a/src/storage/storage_backend_logical.c
+++ b/src/storage/storage_backend_logical.c
@@ -288,7 +288,8 @@ virStorageBackendLogicalMakeVol(char **const groups,
 {
     struct virStorageBackendLogicalPoolVolData *data = opaque;
     virStoragePoolObjPtr pool = data->pool;
-    virStorageVolDefPtr vol = NULL;
+    virPoolObjPtr volobj = NULL;
+    virStorageVolDefPtr voldef = data->vol;
     bool is_new_vol = false;
     int ret = -1;
     const char *attrs = groups[9];
@@ -306,32 +307,30 @@ virStorageBackendLogicalMakeVol(char **const groups,
         return 0;
 
     /* See if we're only looking for a specific volume */
-    if (data->vol != NULL) {
-        vol = data->vol;
-        if (STRNEQ(vol->name, groups[0]))
-            return 0;
-    }
+    if (voldef && STRNEQ(voldef->name, groups[0]))
+        return 0;
 
     /* Or filling in more data on an existing volume */
-    if (vol == NULL)
-        vol = virStorageVolDefFindByName(pool, groups[0]);
+    if (!voldef) {
+        if ((volobj = virStorageVolObjFindByName(pool, groups[0])))
+            voldef = virPoolObjGetDef(volobj);
+    }
 
     /* Or a completely new volume */
-    if (vol == NULL) {
-        if (VIR_ALLOC(vol) < 0)
+    if (!voldef) {
+        if (VIR_ALLOC(voldef) < 0)
             return -1;
 
         is_new_vol = true;
-        vol->type = VIR_STORAGE_VOL_BLOCK;
+        voldef->type = VIR_STORAGE_VOL_BLOCK;
 
-        if (VIR_STRDUP(vol->name, groups[0]) < 0)
+        if (VIR_STRDUP(voldef->name, groups[0]) < 0)
             goto cleanup;
-
     }
 
-    if (vol->target.path == NULL) {
-        if (virAsprintf(&vol->target.path, "%s/%s",
-                        pool->def->target.path, vol->name) < 0)
+    if (!voldef->target.path) {
+        if (virAsprintf(&voldef->target.path, "%s/%s",
+                        pool->def->target.path, voldef->name) < 0)
             goto cleanup;
     }
 
@@ -342,7 +341,7 @@ virStorageBackendLogicalMakeVol(char **const groups,
      * in brackets [] described for the groups[1] (backingStore).
      */
     if (attrs[0] == 's')
-        vol->target.sparse = true;
+        voldef->target.sparse = true;
 
     /* Skips the backingStore of lv created with "--virtualsize",
      * its original device "/dev/$vgname/$lvname_vorigin" is
@@ -352,41 +351,44 @@ virStorageBackendLogicalMakeVol(char **const groups,
      *  lv is created with "--virtualsize").
      */
     if (groups[1] && STRNEQ(groups[1], "") && (groups[1][0] != '[')) {
-        if (VIR_ALLOC(vol->target.backingStore) < 0)
+        if (VIR_ALLOC(voldef->target.backingStore) < 0)
             goto cleanup;
 
-        if (virAsprintf(&vol->target.backingStore->path, "%s/%s",
+        if (virAsprintf(&voldef->target.backingStore->path, "%s/%s",
                         pool->def->target.path, groups[1]) < 0)
             goto cleanup;
 
-        vol->target.backingStore->format = VIR_STORAGE_POOL_LOGICAL_LVM2;
+        voldef->target.backingStore->format = VIR_STORAGE_POOL_LOGICAL_LVM2;
     }
 
-    if (!vol->key && VIR_STRDUP(vol->key, groups[2]) < 0)
+    if (!voldef->key && VIR_STRDUP(voldef->key, groups[2]) < 0)
         goto cleanup;
 
-    if (virStorageBackendUpdateVolInfo(vol, false,
+    if (virStorageBackendUpdateVolInfo(voldef, false,
                                        VIR_STORAGE_VOL_OPEN_DEFAULT, 0) < 0)
         goto cleanup;
 
-    if (virStrToLong_ull(groups[8], NULL, 10, &vol->target.allocation) < 0) {
+    if (virStrToLong_ull(groups[8], NULL, 10, &voldef->target.allocation) < 0) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("malformed volume allocation value"));
         goto cleanup;
     }
 
-    if (virStorageBackendLogicalParseVolExtents(vol, groups) < 0)
+    if (virStorageBackendLogicalParseVolExtents(voldef, groups) < 0)
         goto cleanup;
 
-    if (is_new_vol &&
-        VIR_APPEND_ELEMENT(pool->volumes.objs, pool->volumes.count, vol) < 0)
-        goto cleanup;
+    if (is_new_vol) {
+        if (!(volobj = virStoragePoolObjAddVolume(pool, voldef)))
+            goto cleanup;
+        voldef = NULL;
+        virPoolObjEndAPI(&volobj);
+    }
 
     ret = 0;
 
  cleanup:
     if (is_new_vol)
-        virStorageVolDefFree(vol);
+        virStorageVolDefFree(voldef);
     return ret;
 }
 
diff --git a/src/storage/storage_backend_mpath.c b/src/storage/storage_backend_mpath.c
index a5d692a..514b59b 100644
--- a/src/storage/storage_backend_mpath.c
+++ b/src/storage/storage_backend_mpath.c
@@ -48,6 +48,7 @@ virStorageBackendMpathNewVol(virStoragePoolObjPtr pool,
                              const char *dev)
 {
     virStorageVolDefPtr vol;
+    virPoolObjPtr volobj;
     int ret = -1;
 
     if (VIR_ALLOC(vol) < 0)
@@ -70,16 +71,19 @@ virStorageBackendMpathNewVol(virStoragePoolObjPtr pool,
     if (VIR_STRDUP(vol->key, vol->target.path) < 0)
         goto cleanup;
 
-    if (VIR_APPEND_ELEMENT_COPY(pool->volumes.objs, pool->volumes.count, vol) < 0)
+    if (!(volobj = virStoragePoolObjAddVolume(pool, vol)))
         goto cleanup;
+
+    vol = NULL;
+    virPoolObjEndAPI(&volobj);
+
     pool->def->capacity += vol->target.capacity;
     pool->def->allocation += vol->target.allocation;
     ret = 0;
 
  cleanup:
 
-    if (ret != 0)
-        virStorageVolDefFree(vol);
+    virStorageVolDefFree(vol);
 
     return ret;
 }
diff --git a/src/storage/storage_backend_rbd.c b/src/storage/storage_backend_rbd.c
index 45beb10..5a46664 100644
--- a/src/storage/storage_backend_rbd.c
+++ b/src/storage/storage_backend_rbd.c
@@ -429,6 +429,7 @@ virStorageBackendRBDRefreshPool(virConnectPtr conn,
     int ret = -1;
     int len = -1;
     int r = 0;
+    int count = 0;
     char *name, *names = NULL;
     virStorageBackendRBDStatePtr ptr = NULL;
     struct rados_cluster_stat_t clusterstat;
@@ -473,6 +474,7 @@ virStorageBackendRBDRefreshPool(virConnectPtr conn,
 
     for (name = names; name < names + max_size;) {
         virStorageVolDefPtr vol;
+        virPoolObjPtr volobj;
 
         if (STREQ(name, ""))
             break;
@@ -506,15 +508,17 @@ virStorageBackendRBDRefreshPool(virConnectPtr conn,
             goto cleanup;
         }
 
-        if (VIR_APPEND_ELEMENT(pool->volumes.objs, pool->volumes.count, vol) < 0) {
+        if (!(volobj = virStoragePoolObjAddVolume(pool, vol))) {
             virStorageVolDefFree(vol);
             virStoragePoolObjClearVols(pool);
             goto cleanup;
         }
+        count++;
+        virPoolObjEndAPI(&volobj);
     }
 
-    VIR_DEBUG("Found %zu images in RBD pool %s",
-              pool->volumes.count, pool->def->source.name);
+    VIR_DEBUG("Found %d images in RBD pool %s",
+              count, pool->def->source.name);
 
     ret = 0;
 
diff --git a/src/storage/storage_backend_sheepdog.c b/src/storage/storage_backend_sheepdog.c
index 36458a5..04734c8 100644
--- a/src/storage/storage_backend_sheepdog.c
+++ b/src/storage/storage_backend_sheepdog.c
@@ -115,6 +115,7 @@ virStorageBackendSheepdogAddVolume(virConnectPtr conn ATTRIBUTE_UNUSED,
                                   virStoragePoolObjPtr pool, const char *diskInfo)
 {
     virStorageVolDefPtr vol = NULL;
+    virPoolObjPtr obj;
 
     if (diskInfo == NULL) {
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -130,11 +131,11 @@ virStorageBackendSheepdogAddVolume(virConnectPtr conn ATTRIBUTE_UNUSED,
     if (virStorageBackendSheepdogRefreshVol(conn, pool, vol) < 0)
         goto error;
 
-    if (VIR_EXPAND_N(pool->volumes.objs, pool->volumes.count, 1) < 0)
+    if (!(obj = virStoragePoolObjAddVolume(pool, vol)))
         goto error;
+    vol = NULL;
 
-    pool->volumes.objs[pool->volumes.count - 1] = vol;
-
+    virPoolObjEndAPI(&obj);
     return 0;
 
  error:
diff --git a/src/storage/storage_backend_zfs.c b/src/storage/storage_backend_zfs.c
index 70c533a..fab29fb 100644
--- a/src/storage/storage_backend_zfs.c
+++ b/src/storage/storage_backend_zfs.c
@@ -99,16 +99,17 @@ virStorageBackendZFSCheckPool(virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
 
 static int
 virStorageBackendZFSParseVol(virStoragePoolObjPtr pool,
-                             virStorageVolDefPtr vol,
+                             virStorageVolDefPtr volume,
                              const char *volume_string)
 {
+    virPoolObjPtr volobj = NULL;
+    virStorageVolDefPtr voldef = volume;
     int ret = -1;
     char **tokens;
     size_t count;
     char **name_tokens = NULL;
     char *vol_name;
     bool is_new_vol = false;
-    virStorageVolDefPtr volume = NULL;
 
     if (!(tokens = virStringSplitCount(volume_string, "\t", 0, &count)))
         return -1;
@@ -121,58 +122,60 @@ virStorageBackendZFSParseVol(virStoragePoolObjPtr pool,
 
     vol_name = name_tokens[1];
 
-    if (vol == NULL)
-        volume = virStorageVolDefFindByName(pool, vol_name);
-    else
-        volume = vol;
+    if (!voldef) {
+        if ((volobj = virStorageVolObjFindByName(pool, vol_name)))
+            voldef = virPoolObjGetDef(volobj);
+    }
 
-    if (volume == NULL) {
-        if (VIR_ALLOC(volume) < 0)
+    if (!voldef) {
+        if (VIR_ALLOC(voldef) < 0)
             goto cleanup;
 
         is_new_vol = true;
-        volume->type = VIR_STORAGE_VOL_BLOCK;
+        voldef->type = VIR_STORAGE_VOL_BLOCK;
 
-        if (VIR_STRDUP(volume->name, vol_name) < 0)
+        if (VIR_STRDUP(voldef->name, vol_name) < 0)
             goto cleanup;
     }
 
-    if (!volume->key && VIR_STRDUP(volume->key, tokens[0]) < 0)
+    if (!voldef->key && VIR_STRDUP(voldef->key, tokens[0]) < 0)
         goto cleanup;
 
-    if (volume->target.path == NULL) {
-        if (virAsprintf(&volume->target.path, "%s/%s",
-                        pool->def->target.path, volume->name) < 0)
+    if (voldef->target.path == NULL) {
+        if (virAsprintf(&voldef->target.path, "%s/%s",
+                        pool->def->target.path, voldef->name) < 0)
             goto cleanup;
     }
 
-    if (virStrToLong_ull(tokens[1], NULL, 10, &volume->target.capacity) < 0) {
+    if (virStrToLong_ull(tokens[1], NULL, 10, &voldef->target.capacity) < 0) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("malformed volsize reported"));
         goto cleanup;
     }
 
-    if (virStrToLong_ull(tokens[2], NULL, 10, &volume->target.allocation) < 0) {
+    if (virStrToLong_ull(tokens[2], NULL, 10, &voldef->target.allocation) < 0) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("malformed refreservation reported"));
         goto cleanup;
     }
 
-    if (volume->target.allocation < volume->target.capacity)
-        volume->target.sparse = true;
+    if (voldef->target.allocation < voldef->target.capacity)
+        voldef->target.sparse = true;
 
-    if (is_new_vol &&
-        VIR_APPEND_ELEMENT(pool->volumes.objs,
-                           pool->volumes.count,
-                           volume) < 0)
-        goto cleanup;
+    if (is_new_vol) {
+        if (!(volobj = virStoragePoolObjAddVolume(pool, voldef)))
+            goto cleanup;
+
+        voldef = NULL;
+    }
 
     ret = 0;
  cleanup:
     virStringListFree(tokens);
     virStringListFree(name_tokens);
+    virPoolObjEndAPI(&volobj);
     if (is_new_vol)
-        virStorageVolDefFree(volume);
+        virStorageVolDefFree(voldef);
     return ret;
 }
 
diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
index ed4772a..19f7a88 100644
--- a/src/storage/storage_driver.c
+++ b/src/storage/storage_driver.c
@@ -1370,13 +1370,11 @@ storagePoolSetAutostart(virStoragePoolPtr obj,
     return ret;
 }
 
-
 static int
 storagePoolNumOfVolumes(virStoragePoolPtr obj)
 {
     virStoragePoolObjPtr pool;
     int ret = -1;
-    size_t i;
 
     if (!(pool = virStoragePoolObjFromStoragePool(obj)))
         return -1;
@@ -1389,26 +1387,27 @@ storagePoolNumOfVolumes(virStoragePoolPtr obj)
                        _("storage pool '%s' is not active"), pool->def->name);
         goto cleanup;
     }
-    ret = 0;
-    for (i = 0; i < pool->volumes.count; i++) {
-        if (virStoragePoolNumOfVolumesCheckACL(obj->conn, pool->def,
-                                               pool->volumes.objs[i]))
-            ret++;
-    }
+
+    /* NB: Cannot call filter in List function since the volume ACL filter
+     * function requires 3 instead of 2 params for virPoolObjACLFilter.
+     * Setting up this way fulfills check-aclrules.pl's check that the
+     * driver function calls the CheckACL API */
+    ret = virStoragePoolObjNumOfVolumes(pool->volumes, obj->conn, pool->def,
+                                        virStoragePoolNumOfVolumesCheckACL);
 
  cleanup:
     virStoragePoolObjUnlock(pool);
     return ret;
 }
 
+
 static int
 storagePoolListVolumes(virStoragePoolPtr obj,
                        char **const names,
                        int maxnames)
 {
+    int ret = -1;
     virStoragePoolObjPtr pool;
-    size_t i;
-    int n = 0;
 
     memset(names, 0, maxnames * sizeof(*names));
 
@@ -1424,35 +1423,30 @@ storagePoolListVolumes(virStoragePoolPtr obj,
         goto cleanup;
     }
 
-    for (i = 0; i < pool->volumes.count && n < maxnames; i++) {
-        if (!virStoragePoolListVolumesCheckACL(obj->conn, pool->def,
-                                               pool->volumes.objs[i]))
-            continue;
-        if (VIR_STRDUP(names[n++], pool->volumes.objs[i]->name) < 0)
-            goto cleanup;
-    }
-
-    virStoragePoolObjUnlock(pool);
-    return n;
+    /* NB: Cannot call filter in List function since the volume ACL filter
+     * function requires 3 instead of 2 params for virPoolObjACLFilter.
+     * Setting up this way fulfills check-aclrules.pl's check that the
+     * driver function calls the CheckACL API */
+    ret = virStoragePoolObjListVolumes(pool->volumes, obj->conn, pool->def,
+                                       virStoragePoolListVolumesCheckACL,
+                                       names, maxnames);
 
  cleanup:
     virStoragePoolObjUnlock(pool);
-    for (n = 0; n < maxnames; n++)
-        VIR_FREE(names[n]);
-
-    memset(names, 0, maxnames * sizeof(*names));
-    return -1;
+    return ret;
 }
 
+
 static int
 storagePoolListAllVolumes(virStoragePoolPtr pool,
-                          virStorageVolPtr **vols,
+                          virStorageVolPtr **volumes,
                           unsigned int flags)
 {
     virStoragePoolObjPtr obj;
+    virPoolObjPtr *volobjs = NULL;
+    size_t nvolobjs = 0;
     size_t i;
-    virStorageVolPtr *tmp_vols = NULL;
-    virStorageVolPtr vol = NULL;
+    virStorageVolPtr *vols = NULL;
     int nvols = 0;
     int ret = -1;
 
@@ -1470,40 +1464,45 @@ storagePoolListAllVolumes(virStoragePoolPtr pool,
         goto cleanup;
     }
 
-     /* Just returns the volumes count */
-    if (!vols) {
-        ret = obj->volumes.count;
+    if (virPoolObjTableCollect(obj->volumes, pool->conn, &volobjs, &nvolobjs,
+                               NULL, NULL, flags) < 0)
         goto cleanup;
-    }
 
-    if (VIR_ALLOC_N(tmp_vols, obj->volumes.count + 1) < 0)
-        goto cleanup;
-
-    for (i = 0; i < obj->volumes.count; i++) {
-        if (!virStoragePoolListAllVolumesCheckACL(pool->conn, obj->def,
-                                                  obj->volumes.objs[i]))
-            continue;
-        if (!(vol = virGetStorageVol(pool->conn, obj->def->name,
-                                     obj->volumes.objs[i]->name,
-                                     obj->volumes.objs[i]->key,
-                                     NULL, NULL)))
+    if (volumes) {
+        if (VIR_ALLOC_N(vols, nvolobjs + 1) < 0)
             goto cleanup;
-        tmp_vols[nvols++] = vol;
-    }
 
-    *vols = tmp_vols;
-    tmp_vols = NULL;
-    ret = nvols;
+        for (i = 0; i < nvolobjs; i++) {
+            bool passacl = false;
+            virPoolObjPtr volobj = volobjs[i];
+            virStorageVolDefPtr def;
+
+            virObjectLock(volobj);
+            def = virPoolObjGetDef(volobj);
+            /* NB: Cannot call ACL filter in Collect function since it
+             * takes 3 params and the volume ACL filter requires 3 */
+            if (virStoragePoolListAllVolumesCheckACL(pool->conn, obj->def,
+                                                     obj)) {
+                vols[nvols++] = virGetStorageVol(pool->conn, obj->def->name,
+                                                 def->name, def->key,
+                                                 NULL, NULL);
+                passacl = true;
+            }
+            virObjectUnlock(volobj);
 
- cleanup:
-    if (tmp_vols) {
-        for (i = 0; i < nvols; i++)
-            virObjectUnref(tmp_vols[i]);
-        VIR_FREE(tmp_vols);
+            if (passacl && !vols[i])
+                goto cleanup;
+        }
+
+        *volumes = vols;
+        vols = NULL;
     }
 
-    virStoragePoolObjUnlock(obj);
+    ret = nvols;
 
+ cleanup:
+    virObjectListFree(vols);
+    virObjectListFreeCount(volobjs, nvolobjs);
     return ret;
 }
 
@@ -1512,7 +1511,8 @@ storageVolLookupByName(virStoragePoolPtr obj,
                        const char *name)
 {
     virStoragePoolObjPtr pool;
-    virStorageVolDefPtr vol;
+    virPoolObjPtr volobj = NULL;
+    virStorageVolDefPtr voldef;
     virStorageVolPtr ret = NULL;
 
     if (!(pool = virStoragePoolObjFromStoragePool(obj)))
@@ -1524,22 +1524,22 @@ storageVolLookupByName(virStoragePoolPtr obj,
         goto cleanup;
     }
 
-    vol = virStorageVolDefFindByName(pool, name);
-
-    if (!vol) {
+    if (!(volobj = virStorageVolObjFindByName(pool, name))) {
         virReportError(VIR_ERR_NO_STORAGE_VOL,
                        _("no storage vol with matching name '%s'"),
                        name);
         goto cleanup;
     }
+    voldef = virPoolObjGetDef(volobj);
 
-    if (virStorageVolLookupByNameEnsureACL(obj->conn, pool->def, vol) < 0)
+    if (virStorageVolLookupByNameEnsureACL(obj->conn, pool->def, voldef) < 0)
         goto cleanup;
 
-    ret = virGetStorageVol(obj->conn, pool->def->name, vol->name, vol->key,
-                           NULL, NULL);
+    ret = virGetStorageVol(obj->conn, pool->def->name, voldef->name,
+                           voldef->key, NULL, NULL);
 
  cleanup:
+    virPoolObjEndAPI(&volobj);
     virStoragePoolObjUnlock(pool);
     return ret;
 }
@@ -1556,21 +1556,25 @@ storageVolLookupByKey(virConnectPtr conn,
     for (i = 0; i < driver->pools.count && !ret; i++) {
         virStoragePoolObjLock(driver->pools.objs[i]);
         if (virStoragePoolObjIsActive(driver->pools.objs[i])) {
-            virStorageVolDefPtr vol =
-                virStorageVolDefFindByKey(driver->pools.objs[i], key);
+            virPoolObjPtr volobj;
 
-            if (vol) {
+            if ((volobj = virStorageVolObjFindByKey(driver->pools.objs[i],
+                                                    key))) {
                 virStoragePoolDefPtr def = driver->pools.objs[i]->def;
-                if (virStorageVolLookupByKeyEnsureACL(conn, def, vol) < 0) {
+                virStorageVolDefPtr voldef = virPoolObjGetDef(volobj);
+
+                if (virStorageVolLookupByKeyEnsureACL(conn, def, voldef) < 0) {
+                    virPoolObjEndAPI(&volobj);
                     virStoragePoolObjUnlock(driver->pools.objs[i]);
                     goto cleanup;
                 }
 
                 ret = virGetStorageVol(conn,
                                        def->name,
-                                       vol->name,
-                                       vol->key,
+                                       voldef->name,
+                                       voldef->key,
                                        NULL, NULL);
+                virPoolObjEndAPI(&volobj);
             }
         }
         virStoragePoolObjUnlock(driver->pools.objs[i]);
@@ -1600,7 +1604,7 @@ storageVolLookupByPath(virConnectPtr conn,
     storageDriverLock();
     for (i = 0; i < driver->pools.count && !ret; i++) {
         virStoragePoolObjPtr pool = driver->pools.objs[i];
-        virStorageVolDefPtr vol;
+        virPoolObjPtr volobj = NULL;
         char *stable_path = NULL;
 
         virStoragePoolObjLock(pool);
@@ -1646,18 +1650,22 @@ storageVolLookupByPath(virConnectPtr conn,
                 break;
         }
 
-        vol = virStorageVolDefFindByPath(pool, stable_path);
+        volobj = virStorageVolObjFindByPath(pool, stable_path);
         VIR_FREE(stable_path);
 
-        if (vol) {
-            if (virStorageVolLookupByPathEnsureACL(conn, pool->def, vol) < 0) {
+        if (volobj) {
+            virStorageVolDefPtr voldef = virPoolObjGetDef(volobj);
+            if (virStorageVolLookupByPathEnsureACL(conn, pool->def,
+                                                   voldef) < 0) {
+                virPoolObjEndAPI(&volobj);
                 virStoragePoolObjUnlock(pool);
                 goto cleanup;
             }
 
             ret = virGetStorageVol(conn, pool->def->name,
-                                   vol->name, vol->key,
+                                   voldef->name, voldef->key,
                                    NULL, NULL);
+            virPoolObjEndAPI(&volobj);
         }
 
         virStoragePoolObjUnlock(pool);
@@ -1727,18 +1735,21 @@ static void
 storageVolRemoveFromPool(virStoragePoolObjPtr pool,
                          virStorageVolDefPtr vol)
 {
-    size_t i;
+    virPoolObjPtr obj;
 
-    for (i = 0; i < pool->volumes.count; i++) {
-        if (pool->volumes.objs[i] == vol) {
-            VIR_INFO("Deleting volume '%s' from storage pool '%s'",
-                     vol->name, pool->def->name);
-            virStorageVolDefFree(vol);
-
-            VIR_DELETE_ELEMENT(pool->volumes.objs, i, pool->volumes.count);
-            break;
-        }
+    if (!(obj = virPoolObjTableFindByName(pool->volumes, vol->name))) {
+        virReportError(VIR_ERR_NO_STORAGE_VOL,
+                       _("no storage vol with matching name '%s'"),
+                       vol->name);
+        return;
     }
+
+    VIR_INFO("Deleting volume '%s' from storage pool '%s'",
+              vol->name, pool->def->name);
+
+    virStoragePoolObjRemoveVolume(pool, &obj);
+
+    virPoolObjEndAPI(&obj);
 }
 
 
@@ -1781,23 +1792,23 @@ storageVolDeleteInternal(virStorageVolPtr obj,
 }
 
 
-static virStorageVolDefPtr
-virStorageVolDefFromVol(virStorageVolPtr obj,
+static virPoolObjPtr
+virStorageVolObjFromVol(virStorageVolPtr volume,
                         virStoragePoolObjPtr *pool,
                         virStorageBackendPtr *backend)
 {
-    virStorageVolDefPtr vol = NULL;
+    virPoolObjPtr volobj = NULL;
 
     *pool = NULL;
 
     storageDriverLock();
-    *pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
+    *pool = virStoragePoolObjFindByName(&driver->pools, volume->pool);
     storageDriverUnlock();
 
     if (!*pool) {
         virReportError(VIR_ERR_NO_STORAGE_POOL,
                        _("no storage pool with matching name '%s'"),
-                       obj->pool);
+                       volume->pool);
         return NULL;
     }
 
@@ -1808,10 +1819,10 @@ virStorageVolDefFromVol(virStorageVolPtr obj,
         goto error;
     }
 
-    if (!(vol = virStorageVolDefFindByName(*pool, obj->name))) {
+    if (!(volobj = virStorageVolObjFindByName(*pool, volume->name))) {
         virReportError(VIR_ERR_NO_STORAGE_VOL,
                        _("no storage vol with matching name '%s'"),
-                       obj->name);
+                       volume->name);
         goto error;
     }
 
@@ -1820,7 +1831,7 @@ virStorageVolDefFromVol(virStorageVolPtr obj,
             goto error;
     }
 
-    return vol;
+    return volobj;
 
  error:
     virStoragePoolObjUnlock(*pool);
@@ -1831,40 +1842,44 @@ virStorageVolDefFromVol(virStorageVolPtr obj,
 
 
 static int
-storageVolDelete(virStorageVolPtr obj,
+storageVolDelete(virStorageVolPtr volume,
                  unsigned int flags)
 {
     virStoragePoolObjPtr pool;
+    virPoolObjPtr volobj;
+    virStorageVolDefPtr voldef;
     virStorageBackendPtr backend;
-    virStorageVolDefPtr vol = NULL;
     int ret = -1;
 
-    if (!(vol = virStorageVolDefFromVol(obj, &pool, &backend)))
+    if (!(volobj = virStorageVolObjFromVol(volume, &pool, &backend)))
         return -1;
+    voldef = virPoolObjGetDef(volobj);
 
-    if (virStorageVolDeleteEnsureACL(obj->conn, pool->def, vol) < 0)
+    if (virStorageVolDeleteEnsureACL(volume->conn, pool->def, voldef) < 0)
         goto cleanup;
 
-    if (vol->in_use) {
+    if (voldef->in_use) {
         virReportError(VIR_ERR_OPERATION_INVALID,
                        _("volume '%s' is still in use."),
-                       vol->name);
+                       voldef->name);
         goto cleanup;
     }
 
-    if (vol->building) {
+    if (voldef->building) {
         virReportError(VIR_ERR_OPERATION_INVALID,
                        _("volume '%s' is still being allocated."),
-                       vol->name);
+                       voldef->name);
         goto cleanup;
     }
 
-    if (storageVolDeleteInternal(obj, backend, pool, vol, flags, true) < 0)
+    if (storageVolDeleteInternal(volume, backend, pool, voldef,
+                                 flags, true) < 0)
         goto cleanup;
 
     ret = 0;
 
  cleanup:
+    virPoolObjEndAPI(&volobj);
     virStoragePoolObjUnlock(pool);
     return ret;
 }
@@ -1878,7 +1893,10 @@ storageVolCreateXML(virStoragePoolPtr obj,
     virStoragePoolObjPtr pool;
     virStorageBackendPtr backend;
     virStorageVolDefPtr voldef = NULL;
-    virStorageVolPtr ret = NULL, volobj = NULL;
+    virStorageVolDefPtr objvoldef;
+    virPoolObjPtr volobj = NULL;
+    virStorageVolPtr vol = NULL;
+    virStorageVolPtr ret = NULL;
 
     virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, NULL);
 
@@ -1894,9 +1912,8 @@ storageVolCreateXML(virStoragePoolPtr obj,
     if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
         goto cleanup;
 
-    voldef = virStorageVolDefParseString(pool->def, xmldesc,
-                                         VIR_VOL_XML_PARSE_OPT_CAPACITY);
-    if (voldef == NULL)
+    if (!(voldef = virStorageVolDefParseString(pool->def, xmldesc,
+                                               VIR_VOL_XML_PARSE_OPT_CAPACITY)))
         goto cleanup;
 
     if (!voldef->target.capacity && !backend->buildVol) {
@@ -1909,7 +1926,7 @@ storageVolCreateXML(virStoragePoolPtr obj,
     if (virStorageVolCreateXMLEnsureACL(obj->conn, pool->def, voldef) < 0)
         goto cleanup;
 
-    if (virStorageVolDefFindByName(pool, voldef->name)) {
+    if ((volobj = virStorageVolObjFindByName(pool, voldef->name))) {
         virReportError(VIR_ERR_STORAGE_VOL_EXIST,
                        _("'%s'"), voldef->name);
         goto cleanup;
@@ -1922,43 +1939,38 @@ storageVolCreateXML(virStoragePoolPtr obj,
         goto cleanup;
     }
 
-    if (VIR_REALLOC_N(pool->volumes.objs,
-                      pool->volumes.count+1) < 0)
-        goto cleanup;
-
     /* Wipe any key the user may have suggested, as volume creation
      * will generate the canonical key.  */
     VIR_FREE(voldef->key);
     if (backend->createVol(obj->conn, pool, voldef) < 0)
         goto cleanup;
 
-    pool->volumes.objs[pool->volumes.count++] = voldef;
-    volobj = virGetStorageVol(obj->conn, pool->def->name, voldef->name,
-                              voldef->key, NULL, NULL);
-    if (!volobj) {
-        pool->volumes.count--;
+    if (!(volobj = virStoragePoolObjAddVolume(pool, voldef)))
         goto cleanup;
-    }
+    VIR_STEAL_PTR(objvoldef, voldef);
 
+    if (!(vol = virGetStorageVol(obj->conn, pool->def->name, objvoldef->name,
+                                 objvoldef->key, NULL, NULL))) {
+        virStoragePoolObjRemoveVolume(pool, &volobj);
+        goto cleanup;
+    }
 
     if (backend->buildVol) {
         int buildret;
         virStorageVolDefPtr buildvoldef = NULL;
 
-        if (VIR_ALLOC(buildvoldef) < 0) {
-            voldef = NULL;
+        if (VIR_ALLOC(buildvoldef) < 0)
             goto cleanup;
-        }
 
         /* Make a shallow copy of the 'defined' volume definition, since the
          * original allocation value will change as the user polls 'info',
          * but we only need the initial requested values
          */
-        memcpy(buildvoldef, voldef, sizeof(*voldef));
+        memcpy(buildvoldef, objvoldef, sizeof(*objvoldef));
 
         /* Drop the pool lock during volume allocation */
         pool->asyncjobs++;
-        voldef->building = true;
+        objvoldef->building = true;
         virStoragePoolObjUnlock(pool);
 
         buildret = backend->buildVol(obj->conn, pool, buildvoldef, flags);
@@ -1969,23 +1981,21 @@ storageVolCreateXML(virStoragePoolPtr obj,
         virStoragePoolObjLock(pool);
         storageDriverUnlock();
 
-        voldef->building = false;
+        objvoldef->building = false;
         pool->asyncjobs--;
 
         if (buildret < 0) {
             /* buildVol handles deleting volume on failure */
-            storageVolRemoveFromPool(pool, voldef);
-            voldef = NULL;
+            storageVolRemoveFromPool(pool, objvoldef);
             goto cleanup;
         }
 
     }
 
     if (backend->refreshVol &&
-        backend->refreshVol(obj->conn, pool, voldef) < 0) {
-        storageVolDeleteInternal(volobj, backend, pool, voldef,
+        backend->refreshVol(obj->conn, pool, objvoldef) < 0) {
+        storageVolDeleteInternal(vol, backend, pool, objvoldef,
                                  0, false);
-        voldef = NULL;
         goto cleanup;
     }
 
@@ -1993,18 +2003,18 @@ storageVolCreateXML(virStoragePoolPtr obj,
      * it updates the pool values.
      */
     if (pool->def->type != VIR_STORAGE_POOL_DISK) {
-        pool->def->allocation += voldef->target.allocation;
-        pool->def->available -= voldef->target.allocation;
+        pool->def->allocation += objvoldef->target.allocation;
+        pool->def->available -= objvoldef->target.allocation;
     }
 
     VIR_INFO("Creating volume '%s' in storage pool '%s'",
-             volobj->name, pool->def->name);
-    ret = volobj;
-    volobj = NULL;
-    voldef = NULL;
+             vol->name, pool->def->name);
+    ret = vol;
+    vol = NULL;
 
  cleanup:
-    virObjectUnref(volobj);
+    virPoolObjEndAPI(&volobj);
+    virObjectUnref(vol);
     virStorageVolDefFree(voldef);
     if (pool)
         virStoragePoolObjUnlock(pool);
@@ -2014,13 +2024,19 @@ storageVolCreateXML(virStoragePoolPtr obj,
 static virStorageVolPtr
 storageVolCreateXMLFrom(virStoragePoolPtr obj,
                         const char *xmldesc,
-                        virStorageVolPtr vobj,
+                        virStorageVolPtr volume,
                         unsigned int flags)
 {
     virStoragePoolObjPtr pool, origpool = NULL;
     virStorageBackendPtr backend;
-    virStorageVolDefPtr origvol = NULL, newvol = NULL, shadowvol = NULL;
-    virStorageVolPtr ret = NULL, volobj = NULL;
+    virPoolObjPtr newvolobj = NULL;
+    virPoolObjPtr origvolobj = NULL;
+    virStorageVolDefPtr origvoldef;
+    virStorageVolDefPtr newvoldef = NULL;
+    virStorageVolDefPtr objnewvoldef;
+    virStorageVolDefPtr shadowvoldef = NULL;
+    virStorageVolPtr vol = NULL;
+    virStorageVolPtr ret = NULL;
     int buildret;
 
     virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA |
@@ -2029,9 +2045,9 @@ storageVolCreateXMLFrom(virStoragePoolPtr obj,
 
     storageDriverLock();
     pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
-    if (pool && STRNEQ(obj->name, vobj->pool)) {
+    if (pool && STRNEQ(obj->name, volume->pool)) {
         virStoragePoolObjUnlock(pool);
-        origpool = virStoragePoolObjFindByName(&driver->pools, vobj->pool);
+        origpool = virStoragePoolObjFindByName(&driver->pools, volume->pool);
         virStoragePoolObjLock(pool);
     }
     storageDriverUnlock();
@@ -2044,10 +2060,10 @@ storageVolCreateXMLFrom(virStoragePoolPtr obj,
         goto cleanup;
     }
 
-    if (STRNEQ(obj->name, vobj->pool) && !origpool) {
+    if (STRNEQ(obj->name, volume->pool) && !origpool) {
         virReportError(VIR_ERR_NO_STORAGE_POOL,
                        _("no storage pool with matching name '%s'"),
-                       vobj->pool);
+                       volume->pool);
         goto cleanup;
     }
 
@@ -2067,41 +2083,42 @@ storageVolCreateXMLFrom(virStoragePoolPtr obj,
     if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
         goto cleanup;
 
-    origvol = virStorageVolDefFindByName(origpool ?
-                                         origpool : pool, vobj->name);
-    if (!origvol) {
+    if (!(origvolobj = virStorageVolObjFindByName(origpool ? origpool :
+                                                  pool, volume->name))) {
         virReportError(VIR_ERR_NO_STORAGE_VOL,
                        _("no storage vol with matching name '%s'"),
-                       vobj->name);
+                       volume->name);
         goto cleanup;
     }
+    origvoldef = virPoolObjGetDef(origvolobj);
 
-    newvol = virStorageVolDefParseString(pool->def, xmldesc,
-                                         VIR_VOL_XML_PARSE_NO_CAPACITY);
-    if (newvol == NULL)
+    if (!(newvoldef =
+          virStorageVolDefParseString(pool->def, xmldesc,
+                                      VIR_VOL_XML_PARSE_NO_CAPACITY)))
         goto cleanup;
 
-    if (virStorageVolCreateXMLFromEnsureACL(obj->conn, pool->def, newvol) < 0)
+    if (virStorageVolCreateXMLFromEnsureACL(obj->conn, pool->def,
+                                            newvoldef) < 0)
         goto cleanup;
 
-    if (virStorageVolDefFindByName(pool, newvol->name)) {
+    if ((newvolobj = virStorageVolObjFindByName(pool, newvoldef->name))) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("storage volume name '%s' already in use."),
-                       newvol->name);
+                       newvoldef->name);
         goto cleanup;
     }
 
     /* Use the original volume's capacity in case the new capacity
      * is less than that, or it was omitted */
-    if (newvol->target.capacity < origvol->target.capacity)
-        newvol->target.capacity = origvol->target.capacity;
+    if (newvoldef->target.capacity < origvoldef->target.capacity)
+        newvoldef->target.capacity = origvoldef->target.capacity;
 
     /* If the allocation was not provided in the XML, then use capacity
      * as it's specifically documented "If omitted when creating a volume,
      * the  volume will be fully allocated at time of creation.". This
      * is especially important for logical volume creation. */
-    if (!newvol->target.has_allocation)
-        newvol->target.allocation = newvol->target.capacity;
+    if (!newvoldef->target.has_allocation)
+        newvoldef->target.allocation = newvoldef->target.capacity;
 
     if (!backend->buildVolFrom) {
         virReportError(VIR_ERR_NO_SUPPORT,
@@ -2110,49 +2127,47 @@ storageVolCreateXMLFrom(virStoragePoolPtr obj,
         goto cleanup;
     }
 
-    if (origvol->building) {
+    if (origvoldef->building) {
         virReportError(VIR_ERR_OPERATION_INVALID,
                        _("volume '%s' is still being allocated."),
-                       origvol->name);
+                       origvoldef->name);
         goto cleanup;
     }
 
     if (backend->refreshVol &&
-        backend->refreshVol(obj->conn, pool, origvol) < 0)
-        goto cleanup;
-
-    if (VIR_REALLOC_N(pool->volumes.objs,
-                      pool->volumes.count+1) < 0)
+        backend->refreshVol(obj->conn, pool, origvoldef) < 0)
         goto cleanup;
 
     /* 'Define' the new volume so we get async progress reporting.
      * Wipe any key the user may have suggested, as volume creation
      * will generate the canonical key.  */
-    VIR_FREE(newvol->key);
-    if (backend->createVol(obj->conn, pool, newvol) < 0)
+    VIR_FREE(newvoldef->key);
+    if (backend->createVol(obj->conn, pool, newvoldef) < 0)
         goto cleanup;
 
     /* Make a shallow copy of the 'defined' volume definition, since the
      * original allocation value will change as the user polls 'info',
      * but we only need the initial requested values
      */
-    if (VIR_ALLOC(shadowvol) < 0)
+    if (VIR_ALLOC(shadowvoldef) < 0)
         goto cleanup;
 
-    memcpy(shadowvol, newvol, sizeof(*newvol));
+    memcpy(shadowvoldef, newvoldef, sizeof(*newvoldef));
+
+    if (!(newvolobj = virStoragePoolObjAddVolume(pool, newvoldef)))
+        goto cleanup;
+    VIR_STEAL_PTR(objnewvoldef, newvoldef);
 
-    pool->volumes.objs[pool->volumes.count++] = newvol;
-    volobj = virGetStorageVol(obj->conn, pool->def->name, newvol->name,
-                              newvol->key, NULL, NULL);
-    if (!volobj) {
-        pool->volumes.count--;
+    if (!(vol = virGetStorageVol(obj->conn, pool->def->name, objnewvoldef->name,
+                                 objnewvoldef->key, NULL, NULL))) {
+        virStoragePoolObjRemoveVolume(pool, &newvolobj);
         goto cleanup;
     }
 
     /* Drop the pool lock during volume allocation */
     pool->asyncjobs++;
-    newvol->building = true;
-    origvol->in_use++;
+    objnewvoldef->building = true;
+    origvoldef->in_use++;
     virStoragePoolObjUnlock(pool);
 
     if (origpool) {
@@ -2160,7 +2175,8 @@ storageVolCreateXMLFrom(virStoragePoolPtr obj,
         virStoragePoolObjUnlock(origpool);
     }
 
-    buildret = backend->buildVolFrom(obj->conn, pool, shadowvol, origvol, flags);
+    buildret = backend->buildVolFrom(obj->conn, pool, shadowvoldef,
+                                     origvoldef, flags);
 
     storageDriverLock();
     virStoragePoolObjLock(pool);
@@ -2168,8 +2184,8 @@ storageVolCreateXMLFrom(virStoragePoolPtr obj,
         virStoragePoolObjLock(origpool);
     storageDriverUnlock();
 
-    origvol->in_use--;
-    newvol->building = false;
+    origvoldef->in_use--;
+    objnewvoldef->building = false;
     pool->asyncjobs--;
 
     if (origpool) {
@@ -2180,9 +2196,8 @@ storageVolCreateXMLFrom(virStoragePoolPtr obj,
 
     if (buildret < 0 ||
         (backend->refreshVol &&
-         backend->refreshVol(obj->conn, pool, newvol) < 0)) {
-        storageVolDeleteInternal(volobj, backend, pool, newvol, 0, false);
-        newvol = NULL;
+         backend->refreshVol(obj->conn, pool, objnewvoldef) < 0)) {
+        storageVolDeleteInternal(vol, backend, pool, objnewvoldef, 0, false);
         goto cleanup;
     }
 
@@ -2190,20 +2205,21 @@ storageVolCreateXMLFrom(virStoragePoolPtr obj,
      * it updates the pool values
      */
     if (pool->def->type != VIR_STORAGE_POOL_DISK) {
-        pool->def->allocation += newvol->target.allocation;
-        pool->def->available -= newvol->target.allocation;
+        pool->def->allocation += objnewvoldef->target.allocation;
+        pool->def->available -= objnewvoldef->target.allocation;
     }
 
     VIR_INFO("Creating volume '%s' in storage pool '%s'",
-             volobj->name, pool->def->name);
-    ret = volobj;
-    volobj = NULL;
-    newvol = NULL;
+             vol->name, pool->def->name);
+    ret = vol;
+    vol = NULL;
 
  cleanup:
-    virObjectUnref(volobj);
-    virStorageVolDefFree(newvol);
-    VIR_FREE(shadowvol);
+    virPoolObjEndAPI(&origvolobj);
+    virPoolObjEndAPI(&newvolobj);
+    virObjectUnref(vol);
+    virStorageVolDefFree(newvoldef);
+    VIR_FREE(shadowvoldef);
     if (pool)
         virStoragePoolObjUnlock(pool);
     if (origpool)
@@ -2213,7 +2229,7 @@ storageVolCreateXMLFrom(virStoragePoolPtr obj,
 
 
 static int
-storageVolDownload(virStorageVolPtr obj,
+storageVolDownload(virStorageVolPtr volume,
                    virStreamPtr stream,
                    unsigned long long offset,
                    unsigned long long length,
@@ -2221,21 +2237,23 @@ storageVolDownload(virStorageVolPtr obj,
 {
     virStorageBackendPtr backend;
     virStoragePoolObjPtr pool = NULL;
-    virStorageVolDefPtr vol = NULL;
+    virPoolObjPtr volobj;
+    virStorageVolDefPtr voldef;
     int ret = -1;
 
     virCheckFlags(0, -1);
 
-    if (!(vol = virStorageVolDefFromVol(obj, &pool, &backend)))
+    if (!(volobj = virStorageVolObjFromVol(volume, &pool, &backend)))
         return -1;
+    voldef = virPoolObjGetDef(volobj);
 
-    if (virStorageVolDownloadEnsureACL(obj->conn, pool->def, vol) < 0)
+    if (virStorageVolDownloadEnsureACL(volume->conn, pool->def, voldef) < 0)
         goto cleanup;
 
-    if (vol->building) {
+    if (voldef->building) {
         virReportError(VIR_ERR_OPERATION_INVALID,
                        _("volume '%s' is still being allocated."),
-                       vol->name);
+                       voldef->name);
         goto cleanup;
     }
 
@@ -2245,10 +2263,11 @@ storageVolDownload(virStorageVolPtr obj,
         goto cleanup;
     }
 
-    ret = backend->downloadVol(obj->conn, pool, vol, stream,
+    ret = backend->downloadVol(volume->conn, pool, voldef, stream,
                                offset, length, flags);
 
  cleanup:
+    virPoolObjEndAPI(&volobj);
     virStoragePoolObjUnlock(pool);
 
     return ret;
@@ -2380,7 +2399,7 @@ virStorageVolFDStreamCloseCb(virStreamPtr st ATTRIBUTE_UNUSED,
 }
 
 static int
-storageVolUpload(virStorageVolPtr obj,
+storageVolUpload(virStorageVolPtr volume,
                  virStreamPtr stream,
                  unsigned long long offset,
                  unsigned long long length,
@@ -2388,29 +2407,31 @@ storageVolUpload(virStorageVolPtr obj,
 {
     virStorageBackendPtr backend;
     virStoragePoolObjPtr pool = NULL;
-    virStorageVolDefPtr vol = NULL;
+    virPoolObjPtr volobj;
+    virStorageVolDefPtr voldef;
     virStorageVolStreamInfoPtr cbdata = NULL;
     int ret = -1;
 
     virCheckFlags(0, -1);
 
-    if (!(vol = virStorageVolDefFromVol(obj, &pool, &backend)))
+    if (!(volobj = virStorageVolObjFromVol(volume, &pool, &backend)))
         return -1;
+    voldef = virPoolObjGetDef(volobj);
 
-    if (virStorageVolUploadEnsureACL(obj->conn, pool->def, vol) < 0)
+    if (virStorageVolUploadEnsureACL(volume->conn, pool->def, voldef) < 0)
         goto cleanup;
 
-    if (vol->in_use) {
+    if (voldef->in_use) {
         virReportError(VIR_ERR_OPERATION_INVALID,
                        _("volume '%s' is still in use."),
-                       vol->name);
+                       voldef->name);
         goto cleanup;
     }
 
-    if (vol->building) {
+    if (voldef->building) {
         virReportError(VIR_ERR_OPERATION_INVALID,
                        _("volume '%s' is still being allocated."),
-                       vol->name);
+                       voldef->name);
         goto cleanup;
     }
 
@@ -2429,11 +2450,11 @@ storageVolUpload(virStorageVolPtr obj,
     if (VIR_ALLOC(cbdata) < 0 ||
         VIR_STRDUP(cbdata->pool_name, pool->def->name) < 0)
         goto cleanup;
-    if (vol->type == VIR_STORAGE_VOL_PLOOP &&
-        VIR_STRDUP(cbdata->vol_path, vol->target.path) < 0)
+    if (voldef->type == VIR_STORAGE_VOL_PLOOP &&
+        VIR_STRDUP(cbdata->vol_path, voldef->target.path) < 0)
         goto cleanup;
 
-    if ((ret = backend->uploadVol(obj->conn, pool, vol, stream,
+    if ((ret = backend->uploadVol(volume->conn, pool, voldef, stream,
                                   offset, length, flags)) < 0)
         goto cleanup;
 
@@ -2446,6 +2467,7 @@ storageVolUpload(virStorageVolPtr obj,
     cbdata = NULL;
 
  cleanup:
+    virPoolObjEndAPI(&volobj);
     virStoragePoolObjUnlock(pool);
     if (cbdata)
         virStorageVolPoolRefreshDataFree(cbdata);
@@ -2454,13 +2476,14 @@ storageVolUpload(virStorageVolPtr obj,
 }
 
 static int
-storageVolResize(virStorageVolPtr obj,
+storageVolResize(virStorageVolPtr volume,
                  unsigned long long capacity,
                  unsigned int flags)
 {
     virStorageBackendPtr backend;
     virStoragePoolObjPtr pool = NULL;
-    virStorageVolDefPtr vol = NULL;
+    virPoolObjPtr volobj;
+    virStorageVolDefPtr voldef;
     unsigned long long abs_capacity, delta = 0;
     int ret = -1;
 
@@ -2468,44 +2491,46 @@ storageVolResize(virStorageVolPtr obj,
                   VIR_STORAGE_VOL_RESIZE_DELTA |
                   VIR_STORAGE_VOL_RESIZE_SHRINK, -1);
 
-    if (!(vol = virStorageVolDefFromVol(obj, &pool, &backend)))
+    if (!(volobj = virStorageVolObjFromVol(volume, &pool, &backend)))
         return -1;
+    voldef = virPoolObjGetDef(volobj);
 
-    if (virStorageVolResizeEnsureACL(obj->conn, pool->def, vol) < 0)
+    if (virStorageVolResizeEnsureACL(volume->conn, pool->def, voldef) < 0)
         goto cleanup;
 
-    if (vol->in_use) {
+    if (voldef->in_use) {
         virReportError(VIR_ERR_OPERATION_INVALID,
                        _("volume '%s' is still in use."),
-                       vol->name);
+                       voldef->name);
         goto cleanup;
     }
 
-    if (vol->building) {
+    if (voldef->building) {
         virReportError(VIR_ERR_OPERATION_INVALID,
                        _("volume '%s' is still being allocated."),
-                       vol->name);
+                       voldef->name);
         goto cleanup;
     }
 
     if (flags & VIR_STORAGE_VOL_RESIZE_DELTA) {
         if (flags & VIR_STORAGE_VOL_RESIZE_SHRINK)
-            abs_capacity = vol->target.capacity - MIN(capacity, vol->target.capacity);
+            abs_capacity = voldef->target.capacity -
+                MIN(capacity, voldef->target.capacity);
         else
-            abs_capacity = vol->target.capacity + capacity;
+            abs_capacity = voldef->target.capacity + capacity;
         flags &= ~VIR_STORAGE_VOL_RESIZE_DELTA;
     } else {
         abs_capacity = capacity;
     }
 
-    if (abs_capacity < vol->target.allocation) {
+    if (abs_capacity < voldef->target.allocation) {
         virReportError(VIR_ERR_INVALID_ARG, "%s",
                        _("can't shrink capacity below "
                          "existing allocation"));
         goto cleanup;
     }
 
-    if (abs_capacity < vol->target.capacity &&
+    if (abs_capacity < voldef->target.capacity &&
         !(flags & VIR_STORAGE_VOL_RESIZE_SHRINK)) {
         virReportError(VIR_ERR_INVALID_ARG, "%s",
                        _("Can't shrink capacity below current "
@@ -2514,7 +2539,7 @@ storageVolResize(virStorageVolPtr obj,
     }
 
     if (flags & VIR_STORAGE_VOL_RESIZE_ALLOCATE)
-        delta = abs_capacity - vol->target.allocation;
+        delta = abs_capacity - voldef->target.allocation;
 
     if (delta > pool->def->available) {
         virReportError(VIR_ERR_OPERATION_FAILED, "%s",
@@ -2529,16 +2554,16 @@ storageVolResize(virStorageVolPtr obj,
         goto cleanup;
     }
 
-    if (backend->resizeVol(obj->conn, pool, vol, abs_capacity, flags) < 0)
+    if (backend->resizeVol(volume->conn, pool, voldef, abs_capacity, flags) < 0)
         goto cleanup;
 
-    vol->target.capacity = abs_capacity;
+    voldef->target.capacity = abs_capacity;
     /* Only update the allocation and pool values if we actually did the
      * allocation; otherwise, this is akin to a create operation with a
      * capacity value different and potentially much larger than available
      */
     if (flags & VIR_STORAGE_VOL_RESIZE_ALLOCATE) {
-        vol->target.allocation = abs_capacity;
+        voldef->target.allocation = abs_capacity;
         pool->def->allocation += delta;
         pool->def->available -= delta;
     }
@@ -2546,6 +2571,7 @@ storageVolResize(virStorageVolPtr obj,
     ret = 0;
 
  cleanup:
+    virPoolObjEndAPI(&volobj);
     virStoragePoolObjUnlock(pool);
 
     return ret;
@@ -2553,13 +2579,14 @@ storageVolResize(virStorageVolPtr obj,
 
 
 static int
-storageVolWipePattern(virStorageVolPtr obj,
+storageVolWipePattern(virStorageVolPtr volume,
                       unsigned int algorithm,
                       unsigned int flags)
 {
     virStorageBackendPtr backend;
     virStoragePoolObjPtr pool = NULL;
-    virStorageVolDefPtr vol = NULL;
+    virPoolObjPtr volobj;
+    virStorageVolDefPtr voldef;
     int ret = -1;
 
     virCheckFlags(0, -1);
@@ -2571,24 +2598,24 @@ storageVolWipePattern(virStorageVolPtr obj,
         return -1;
     }
 
-    if (!(vol = virStorageVolDefFromVol(obj, &pool, &backend)))
+    if (!(volobj = virStorageVolObjFromVol(volume, &pool, &backend)))
         return -1;
+    voldef = virPoolObjGetDef(volobj);
 
-
-    if (virStorageVolWipePatternEnsureACL(obj->conn, pool->def, vol) < 0)
+    if (virStorageVolWipePatternEnsureACL(volume->conn, pool->def, voldef) < 0)
         goto cleanup;
 
-    if (vol->in_use) {
+    if (voldef->in_use) {
         virReportError(VIR_ERR_OPERATION_INVALID,
                        _("volume '%s' is still in use."),
-                       vol->name);
+                       voldef->name);
         goto cleanup;
     }
 
-    if (vol->building) {
+    if (voldef->building) {
         virReportError(VIR_ERR_OPERATION_INVALID,
                        _("volume '%s' is still being allocated."),
-                       vol->name);
+                       voldef->name);
         goto cleanup;
     }
 
@@ -2598,16 +2625,17 @@ storageVolWipePattern(virStorageVolPtr obj,
         goto cleanup;
     }
 
-    if (backend->wipeVol(obj->conn, pool, vol, algorithm, flags) < 0)
+    if (backend->wipeVol(volume->conn, pool, voldef, algorithm, flags) < 0)
         goto cleanup;
 
     if (backend->refreshVol &&
-        backend->refreshVol(obj->conn, pool, vol) < 0)
+        backend->refreshVol(volume->conn, pool, voldef) < 0)
         goto cleanup;
 
     ret = 0;
 
  cleanup:
+    virPoolObjEndAPI(&volobj);
     virStoragePoolObjUnlock(pool);
 
     return ret;
@@ -2622,37 +2650,40 @@ storageVolWipe(virStorageVolPtr obj,
 
 
 static int
-storageVolGetInfoFlags(virStorageVolPtr obj,
+storageVolGetInfoFlags(virStorageVolPtr volume,
                        virStorageVolInfoPtr info,
                        unsigned int flags)
 {
     virStoragePoolObjPtr pool;
     virStorageBackendPtr backend;
-    virStorageVolDefPtr vol;
+    virPoolObjPtr volobj;
+    virStorageVolDefPtr voldef;
     int ret = -1;
 
     virCheckFlags(VIR_STORAGE_VOL_GET_PHYSICAL, -1);
 
-    if (!(vol = virStorageVolDefFromVol(obj, &pool, &backend)))
+    if (!(volobj = virStorageVolObjFromVol(volume, &pool, &backend)))
         return -1;
+    voldef = virPoolObjGetDef(volobj);
 
-    if (virStorageVolGetInfoFlagsEnsureACL(obj->conn, pool->def, vol) < 0)
+    if (virStorageVolGetInfoFlagsEnsureACL(volume->conn, pool->def, voldef) < 0)
         goto cleanup;
 
     if (backend->refreshVol &&
-        backend->refreshVol(obj->conn, pool, vol) < 0)
+        backend->refreshVol(volume->conn, pool, voldef) < 0)
         goto cleanup;
 
     memset(info, 0, sizeof(*info));
-    info->type = vol->type;
-    info->capacity = vol->target.capacity;
+    info->type = voldef->type;
+    info->capacity = voldef->target.capacity;
     if (flags & VIR_STORAGE_VOL_GET_PHYSICAL)
-        info->allocation = vol->target.physical;
+        info->allocation = voldef->target.physical;
     else
-        info->allocation = vol->target.allocation;
+        info->allocation = voldef->target.allocation;
     ret = 0;
 
  cleanup:
+    virPoolObjEndAPI(&volobj);
     virStoragePoolObjUnlock(pool);
     return ret;
 }
@@ -2667,50 +2698,56 @@ storageVolGetInfo(virStorageVolPtr obj,
 
 
 static char *
-storageVolGetXMLDesc(virStorageVolPtr obj,
+storageVolGetXMLDesc(virStorageVolPtr volume,
                      unsigned int flags)
 {
     virStoragePoolObjPtr pool;
     virStorageBackendPtr backend;
-    virStorageVolDefPtr vol;
+    virPoolObjPtr volobj;
+    virStorageVolDefPtr voldef;
     char *ret = NULL;
 
     virCheckFlags(0, NULL);
 
-    if (!(vol = virStorageVolDefFromVol(obj, &pool, &backend)))
+    if (!(volobj = virStorageVolObjFromVol(volume, &pool, &backend)))
         return NULL;
+    voldef = virPoolObjGetDef(volobj);
 
-    if (virStorageVolGetXMLDescEnsureACL(obj->conn, pool->def, vol) < 0)
+    if (virStorageVolGetXMLDescEnsureACL(volume->conn, pool->def, voldef) < 0)
         goto cleanup;
 
     if (backend->refreshVol &&
-        backend->refreshVol(obj->conn, pool, vol) < 0)
+        backend->refreshVol(volume->conn, pool, voldef) < 0)
         goto cleanup;
 
-    ret = virStorageVolDefFormat(pool->def, vol);
+    ret = virStorageVolDefFormat(pool->def, voldef);
 
  cleanup:
+    virPoolObjEndAPI(&volobj);
     virStoragePoolObjUnlock(pool);
 
     return ret;
 }
 
 static char *
-storageVolGetPath(virStorageVolPtr obj)
+storageVolGetPath(virStorageVolPtr volume)
 {
     virStoragePoolObjPtr pool;
-    virStorageVolDefPtr vol;
+    virPoolObjPtr volobj;
+    virStorageVolDefPtr voldef;
     char *ret = NULL;
 
-    if (!(vol = virStorageVolDefFromVol(obj, &pool, NULL)))
+    if (!(volobj = virStorageVolObjFromVol(volume, &pool, NULL)))
         return NULL;
+    voldef = virPoolObjGetDef(volobj);
 
-    if (virStorageVolGetPathEnsureACL(obj->conn, pool->def, vol) < 0)
+    if (virStorageVolGetPathEnsureACL(volume->conn, pool->def, voldef) < 0)
         goto cleanup;
 
-    ignore_value(VIR_STRDUP(ret, vol->target.path));
+    ignore_value(VIR_STRDUP(ret, voldef->target.path));
 
  cleanup:
+    virPoolObjEndAPI(&volobj);
     virStoragePoolObjUnlock(pool);
     return ret;
 }
diff --git a/src/storage/storage_util.c b/src/storage/storage_util.c
index a665bac..644c3e7 100644
--- a/src/storage/storage_util.c
+++ b/src/storage/storage_util.c
@@ -3471,6 +3471,7 @@ virStorageBackendRefreshLocal(virConnectPtr conn ATTRIBUTE_UNUSED,
     struct statvfs sb;
     struct stat statbuf;
     virStorageVolDefPtr vol = NULL;
+    virPoolObjPtr volobj;
     virStorageSourcePtr target = NULL;
     int direrr;
     int fd = -1, ret = -1;
@@ -3539,8 +3540,11 @@ virStorageBackendRefreshLocal(virConnectPtr conn ATTRIBUTE_UNUSED,
              * An error message was raised, but we just continue. */
         }
 
-        if (VIR_APPEND_ELEMENT(pool->volumes.objs, pool->volumes.count, vol) < 0)
+        if (!(volobj = virStoragePoolObjAddVolume(pool, vol)))
             goto cleanup;
+
+        vol = NULL;
+        virPoolObjEndAPI(&volobj);
     }
     if (direrr < 0)
         goto cleanup;
@@ -3656,6 +3660,7 @@ virStorageBackendSCSINewLun(virStoragePoolObjPtr pool,
                             const char *dev)
 {
     virStorageVolDefPtr vol = NULL;
+    virPoolObjPtr volobj;
     char *devpath = NULL;
     int retval = -1;
 
@@ -3727,10 +3732,11 @@ virStorageBackendSCSINewLun(virStoragePoolObjPtr pool,
     pool->def->capacity += vol->target.capacity;
     pool->def->allocation += vol->target.allocation;
 
-    if (VIR_APPEND_ELEMENT(pool->volumes.objs, pool->volumes.count, vol) < 0)
+    if (!(volobj = virStoragePoolObjAddVolume(pool, vol)))
         goto cleanup;
 
     vol = NULL;
+    virPoolObjEndAPI(&volobj);
     retval = 0;
 
  cleanup:
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 51605f3..fedf415 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -1016,7 +1016,9 @@ testOpenVolumesForPool(const char *file,
     size_t i;
     int num, ret = -1;
     xmlNodePtr *nodes = NULL;
+    xmlNodePtr node;
     virStorageVolDefPtr def = NULL;
+    virPoolObjPtr volobj = NULL;
 
     /* Find storage volumes */
     if (virAsprintf(&vol_xpath, "/node/pool[%d]/volume", poolidx) < 0)
@@ -1028,25 +1030,22 @@ testOpenVolumesForPool(const char *file,
         goto error;
 
     for (i = 0; i < num; i++) {
-        xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
-                                                   "volume");
-        if (!node)
+        if (!(node = testParseXMLDocFromFile(nodes[i], file, "volume")))
             goto error;
 
-        def = virStorageVolDefParseNode(pool->def, ctxt->doc, node, 0);
-        if (!def)
+        if (!(def = virStorageVolDefParseNode(pool->def, ctxt->doc, node, 0)))
             goto error;
 
         if (def->target.path == NULL) {
             if (virAsprintf(&def->target.path, "%s/%s",
-                            pool->def->target.path,
-                            def->name) == -1)
+                            pool->def->target.path, def->name) < 0)
                 goto error;
         }
 
         if (!def->key && VIR_STRDUP(def->key, def->target.path) < 0)
             goto error;
-        if (VIR_APPEND_ELEMENT_COPY(pool->volumes.objs, pool->volumes.count, def) < 0)
+
+        if (!(volobj = virStoragePoolObjAddVolume(pool, def)))
             goto error;
 
         pool->def->allocation += def->target.allocation;
@@ -1057,6 +1056,7 @@ testOpenVolumesForPool(const char *file,
 
     ret = 0;
  error:
+    virPoolObjEndAPI(&volobj);
     virStorageVolDefFree(def);
     VIR_FREE(nodes);
     return ret;
@@ -4702,9 +4702,9 @@ testStoragePoolNumOfVolumes(virStoragePoolPtr pool)
                                            pool->name);
     testDriverUnlock(privconn);
 
-    if (privpool == NULL) {
+    if (!privpool) {
         virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
-        goto cleanup;
+        return -1;
     }
 
     if (!virStoragePoolObjIsActive(privpool)) {
@@ -4713,23 +4713,26 @@ testStoragePoolNumOfVolumes(virStoragePoolPtr pool)
         goto cleanup;
     }
 
-    ret = privpool->volumes.count;
+    /* NB: Neither pool->def nor aclfilter is being used for test purposes
+     * so last two args can be NULL */
+    ret = virStoragePoolObjNumOfVolumes(privpool->volumes, pool->conn,
+                                        NULL, NULL);
 
  cleanup:
-    if (privpool)
-        virStoragePoolObjUnlock(privpool);
+    virStoragePoolObjUnlock(privpool);
     return ret;
 }
 
+
+
 static int
 testStoragePoolListVolumes(virStoragePoolPtr pool,
                            char **const names,
                            int maxnames)
 {
+    int ret = -1;
     testDriverPtr privconn = pool->conn->privateData;
     virStoragePoolObjPtr privpool;
-    size_t i = 0;
-    int n = 0;
 
     memset(names, 0, maxnames * sizeof(*names));
 
@@ -4738,47 +4741,39 @@ testStoragePoolListVolumes(virStoragePoolPtr pool,
                                            pool->name);
     testDriverUnlock(privconn);
 
-    if (privpool == NULL) {
+    if (!privpool) {
         virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
-        goto cleanup;
+        return -1;
     }
 
-
     if (!virStoragePoolObjIsActive(privpool)) {
         virReportError(VIR_ERR_OPERATION_INVALID,
                        _("storage pool '%s' is not active"), pool->name);
         goto cleanup;
     }
 
-    for (i = 0; i < privpool->volumes.count && n < maxnames; i++) {
-        if (VIR_STRDUP(names[n++], privpool->volumes.objs[i]->name) < 0)
-            goto cleanup;
-    }
-
-    virStoragePoolObjUnlock(privpool);
-    return n;
+    /* NB: Neither pool->def nor aclfilter is being used for test purposes
+     * so those two args can be NULL */
+    ret = virStoragePoolObjListVolumes(privpool->volumes, pool->conn,
+                                       NULL, NULL, names, maxnames);
 
  cleanup:
-    for (n = 0; n < maxnames; n++)
-        VIR_FREE(names[i]);
-
-    memset(names, 0, maxnames * sizeof(*names));
-    if (privpool)
-        virStoragePoolObjUnlock(privpool);
-    return -1;
+    virStoragePoolObjUnlock(privpool);
+    return ret;
 }
 
+
 static int
 testStoragePoolListAllVolumes(virStoragePoolPtr obj,
-                              virStorageVolPtr **vols,
+                              virStorageVolPtr **volumes,
                               unsigned int flags)
 {
     testDriverPtr privconn = obj->conn->privateData;
     virStoragePoolObjPtr pool;
+    virPoolObjPtr *volobjs = NULL;
+    size_t nvolobjs = 0;
     size_t i;
-    virStorageVolPtr *tmp_vols = NULL;
-    virStorageVolPtr vol = NULL;
-    int nvols = 0;
+    virStorageVolPtr *vols = NULL;
     int ret = -1;
 
     virCheckFlags(0, -1);
@@ -4790,7 +4785,7 @@ testStoragePoolListAllVolumes(virStoragePoolPtr obj,
     if (!pool) {
         virReportError(VIR_ERR_NO_STORAGE_POOL, "%s",
                        _("no storage pool with matching uuid"));
-        goto cleanup;
+        return -1;
     }
 
     if (!virStoragePoolObjIsActive(pool)) {
@@ -4799,40 +4794,39 @@ testStoragePoolListAllVolumes(virStoragePoolPtr obj,
         goto cleanup;
     }
 
-     /* Just returns the volumes count */
-    if (!vols) {
-        ret = pool->volumes.count;
+    if (virPoolObjTableCollect(pool->volumes, obj->conn, &volobjs, &nvolobjs,
+                               NULL, NULL, flags) < 0)
         goto cleanup;
-    }
 
-    if (VIR_ALLOC_N(tmp_vols, pool->volumes.count + 1) < 0)
-         goto cleanup;
-
-    for (i = 0; i < pool->volumes.count; i++) {
-        if (!(vol = virGetStorageVol(obj->conn, pool->def->name,
-                                     pool->volumes.objs[i]->name,
-                                     pool->volumes.objs[i]->key,
-                                     NULL, NULL)))
+    if (volumes) {
+        if (VIR_ALLOC_N(vols, nvolobjs + 1) < 0)
             goto cleanup;
-        tmp_vols[nvols++] = vol;
-    }
 
-    *vols = tmp_vols;
-    tmp_vols = NULL;
-    ret = nvols;
+        for (i = 0; i < nvolobjs; i++) {
+            virPoolObjPtr volobj = volobjs[i];
+            virStorageVolDefPtr def;
 
- cleanup:
-    if (tmp_vols) {
-        for (i = 0; i < nvols; i++) {
-            if (tmp_vols[i])
-                virStorageVolFree(tmp_vols[i]);
+            virObjectLock(volobj);
+            def = virPoolObjGetDef(volobj);
+            vols[i] = virGetStorageVol(obj->conn, pool->def->name,
+                                       def->name, def->key, NULL, NULL);
+            virObjectUnlock(volobj);
+
+            if (!vols[i])
+                goto cleanup;
         }
-        VIR_FREE(tmp_vols);
+
+        *volumes = vols;
+        vols = NULL;
     }
 
-    if (pool)
-        virStoragePoolObjUnlock(pool);
+    ret = nvolobjs;
 
+ cleanup:
+    virObjectListFree(vols);
+    virObjectListFreeCount(volobjs, nvolobjs);
+
+    virStoragePoolObjUnlock(pool);
     return ret;
 }
 
@@ -4842,7 +4836,8 @@ testStorageVolLookupByName(virStoragePoolPtr pool,
 {
     testDriverPtr privconn = pool->conn->privateData;
     virStoragePoolObjPtr privpool;
-    virStorageVolDefPtr privvol;
+    virPoolObjPtr volobj = NULL;
+    virStorageVolDefPtr voldef;
     virStorageVolPtr ret = NULL;
 
     testDriverLock(privconn);
@@ -4862,19 +4857,19 @@ testStorageVolLookupByName(virStoragePoolPtr pool,
         goto cleanup;
     }
 
-    privvol = virStorageVolDefFindByName(privpool, name);
-
-    if (!privvol) {
+    if (!(volobj = virStorageVolObjFindByName(privpool, name))) {
         virReportError(VIR_ERR_NO_STORAGE_VOL,
                        _("no storage vol with matching name '%s'"), name);
         goto cleanup;
     }
+    voldef = virPoolObjGetDef(volobj);
 
     ret = virGetStorageVol(pool->conn, privpool->def->name,
-                           privvol->name, privvol->key,
+                           voldef->name, voldef->key,
                            NULL, NULL);
 
  cleanup:
+    virPoolObjEndAPI(&volobj);
     if (privpool)
         virStoragePoolObjUnlock(privpool);
     return ret;
@@ -4886,6 +4881,8 @@ testStorageVolLookupByKey(virConnectPtr conn,
                           const char *key)
 {
     testDriverPtr privconn = conn->privateData;
+    virPoolObjPtr volobj;
+    virStorageVolDefPtr voldef;
     size_t i;
     virStorageVolPtr ret = NULL;
 
@@ -4893,18 +4890,19 @@ testStorageVolLookupByKey(virConnectPtr conn,
     for (i = 0; i < privconn->pools.count; i++) {
         virStoragePoolObjLock(privconn->pools.objs[i]);
         if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
-            virStorageVolDefPtr privvol =
-                virStorageVolDefFindByKey(privconn->pools.objs[i], key);
-
-            if (privvol) {
-                ret = virGetStorageVol(conn,
-                                       privconn->pools.objs[i]->def->name,
-                                       privvol->name,
-                                       privvol->key,
-                                       NULL, NULL);
-                virStoragePoolObjUnlock(privconn->pools.objs[i]);
-                break;
-            }
+            if (!(volobj = virStorageVolObjFindByKey(privconn->pools.objs[i],
+                                                     key)))
+                continue;
+            voldef = virPoolObjGetDef(volobj);
+
+            ret = virGetStorageVol(conn,
+                                   privconn->pools.objs[i]->def->name,
+                                   voldef->name,
+                                   voldef->key,
+                                   NULL, NULL);
+            virPoolObjEndAPI(&volobj);
+            virStoragePoolObjUnlock(privconn->pools.objs[i]);
+            break;
         }
         virStoragePoolObjUnlock(privconn->pools.objs[i]);
     }
@@ -4922,6 +4920,8 @@ testStorageVolLookupByPath(virConnectPtr conn,
                            const char *path)
 {
     testDriverPtr privconn = conn->privateData;
+    virPoolObjPtr volobj;
+    virStorageVolDefPtr voldef;
     size_t i;
     virStorageVolPtr ret = NULL;
 
@@ -4929,18 +4929,19 @@ testStorageVolLookupByPath(virConnectPtr conn,
     for (i = 0; i < privconn->pools.count; i++) {
         virStoragePoolObjLock(privconn->pools.objs[i]);
         if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
-            virStorageVolDefPtr privvol =
-                virStorageVolDefFindByPath(privconn->pools.objs[i], path);
-
-            if (privvol) {
-                ret = virGetStorageVol(conn,
-                                       privconn->pools.objs[i]->def->name,
-                                       privvol->name,
-                                       privvol->key,
-                                       NULL, NULL);
-                virStoragePoolObjUnlock(privconn->pools.objs[i]);
-                break;
-            }
+            if (!(volobj = virStorageVolObjFindByPath(privconn->pools.objs[i],
+                                                      path)))
+                continue;
+            voldef = virPoolObjGetDef(volobj);
+
+            ret = virGetStorageVol(conn,
+                                   privconn->pools.objs[i]->def->name,
+                                   voldef->name,
+                                   voldef->key,
+                                   NULL, NULL);
+            virPoolObjEndAPI(&volobj);
+            virStoragePoolObjUnlock(privconn->pools.objs[i]);
+            break;
         }
         virStoragePoolObjUnlock(privconn->pools.objs[i]);
     }
@@ -4960,7 +4961,9 @@ testStorageVolCreateXML(virStoragePoolPtr pool,
 {
     testDriverPtr privconn = pool->conn->privateData;
     virStoragePoolObjPtr privpool;
-    virStorageVolDefPtr privvol = NULL;
+    virStorageVolDefPtr voldef = NULL;
+    virPoolObjPtr volobj = NULL;
+    virStorageVolDefPtr objvoldef;
     virStorageVolPtr ret = NULL;
 
     virCheckFlags(0, NULL);
@@ -4981,46 +4984,48 @@ testStorageVolCreateXML(virStoragePoolPtr pool,
         goto cleanup;
     }
 
-    privvol = virStorageVolDefParseString(privpool->def, xmldesc, 0);
-    if (privvol == NULL)
+    if (!(voldef = virStorageVolDefParseString(privpool->def, xmldesc, 0)))
         goto cleanup;
 
-    if (virStorageVolDefFindByName(privpool, privvol->name)) {
+    if ((volobj = virStorageVolObjFindByName(privpool, voldef->name))) {
         virReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("storage vol already exists"));
         goto cleanup;
     }
 
     /* Make sure enough space */
-    if ((privpool->def->allocation + privvol->target.allocation) >
+    if ((privpool->def->allocation + voldef->target.allocation) >
          privpool->def->capacity) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Not enough free space in pool for volume '%s'"),
-                       privvol->name);
+                       voldef->name);
         goto cleanup;
     }
 
-    if (virAsprintf(&privvol->target.path, "%s/%s",
+    if (virAsprintf(&voldef->target.path, "%s/%s",
                     privpool->def->target.path,
-                    privvol->name) == -1)
+                    voldef->name) == -1)
+        goto cleanup;
+
+    if (VIR_STRDUP(voldef->key, voldef->target.path) < 0)
         goto cleanup;
 
-    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0 ||
-        VIR_APPEND_ELEMENT_COPY(privpool->volumes.objs,
-                                privpool->volumes.count, privvol) < 0)
+    if (!(volobj = virStoragePoolObjAddVolume(privpool, voldef)))
         goto cleanup;
+    VIR_STEAL_PTR(objvoldef, voldef);
 
-    privpool->def->allocation += privvol->target.allocation;
+    privpool->def->allocation += objvoldef->target.allocation;
     privpool->def->available = (privpool->def->capacity -
                                 privpool->def->allocation);
 
-    ret = virGetStorageVol(pool->conn, privpool->def->name,
-                           privvol->name, privvol->key,
-                           NULL, NULL);
-    privvol = NULL;
+    if (!(ret = virGetStorageVol(pool->conn, privpool->def->name,
+                                 objvoldef->name, objvoldef->key,
+                                 NULL, NULL)))
+        virStoragePoolObjRemoveVolume(privpool, &volobj);
 
  cleanup:
-    virStorageVolDefFree(privvol);
+    virPoolObjEndAPI(&volobj);
+    virStorageVolDefFree(voldef);
     if (privpool)
         virStoragePoolObjUnlock(privpool);
     return ret;
@@ -5034,7 +5039,10 @@ testStorageVolCreateXMLFrom(virStoragePoolPtr pool,
 {
     testDriverPtr privconn = pool->conn->privateData;
     virStoragePoolObjPtr privpool;
-    virStorageVolDefPtr privvol = NULL, origvol = NULL;
+    virStorageVolDefPtr voldef = NULL;
+    virPoolObjPtr volobj = NULL;
+    virStorageVolDefPtr objvoldef;
+    virPoolObjPtr origvolobj = NULL;
     virStorageVolPtr ret = NULL;
 
     virCheckFlags(0, NULL);
@@ -5055,18 +5063,16 @@ testStorageVolCreateXMLFrom(virStoragePoolPtr pool,
         goto cleanup;
     }
 
-    privvol = virStorageVolDefParseString(privpool->def, xmldesc, 0);
-    if (privvol == NULL)
+    if (!(voldef = virStorageVolDefParseString(privpool->def, xmldesc, 0)))
         goto cleanup;
 
-    if (virStorageVolDefFindByName(privpool, privvol->name)) {
+    if ((volobj = virStorageVolObjFindByName(privpool, voldef->name))) {
         virReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("storage vol already exists"));
         goto cleanup;
     }
 
-    origvol = virStorageVolDefFindByName(privpool, clonevol->name);
-    if (!origvol) {
+    if (!(origvolobj = virStorageVolObjFindByName(privpool, clonevol->name))) {
         virReportError(VIR_ERR_NO_STORAGE_VOL,
                        _("no storage vol with matching name '%s'"),
                        clonevol->name);
@@ -5074,57 +5080,61 @@ testStorageVolCreateXMLFrom(virStoragePoolPtr pool,
     }
 
     /* Make sure enough space */
-    if ((privpool->def->allocation + privvol->target.allocation) >
+    if ((privpool->def->allocation + voldef->target.allocation) >
          privpool->def->capacity) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Not enough free space in pool for volume '%s'"),
-                       privvol->name);
+                       voldef->name);
         goto cleanup;
     }
     privpool->def->available = (privpool->def->capacity -
                                 privpool->def->allocation);
 
-    if (virAsprintf(&privvol->target.path, "%s/%s",
+    if (virAsprintf(&voldef->target.path, "%s/%s",
                     privpool->def->target.path,
-                    privvol->name) == -1)
+                    voldef->name) == -1)
         goto cleanup;
 
-    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0 ||
-        VIR_APPEND_ELEMENT_COPY(privpool->volumes.objs,
-                                privpool->volumes.count, privvol) < 0)
+    if (VIR_STRDUP(voldef->key, voldef->target.path) < 0)
         goto cleanup;
 
-    privpool->def->allocation += privvol->target.allocation;
+    if (!(volobj = virStoragePoolObjAddVolume(privpool, voldef)))
+        goto cleanup;
+    VIR_STEAL_PTR(objvoldef, voldef);
+
+    privpool->def->allocation += objvoldef->target.allocation;
     privpool->def->available = (privpool->def->capacity -
                                 privpool->def->allocation);
 
-    ret = virGetStorageVol(pool->conn, privpool->def->name,
-                           privvol->name, privvol->key,
-                           NULL, NULL);
-    privvol = NULL;
+    if (!(ret = virGetStorageVol(pool->conn, privpool->def->name,
+                                 objvoldef->name, objvoldef->key,
+                                 NULL, NULL)))
+        virStoragePoolObjRemoveVolume(privpool, &volobj);
 
  cleanup:
-    virStorageVolDefFree(privvol);
+    virPoolObjEndAPI(&origvolobj);
+    virPoolObjEndAPI(&volobj);
+    virStorageVolDefFree(voldef);
     if (privpool)
         virStoragePoolObjUnlock(privpool);
     return ret;
 }
 
 static int
-testStorageVolDelete(virStorageVolPtr vol,
+testStorageVolDelete(virStorageVolPtr volume,
                      unsigned int flags)
 {
-    testDriverPtr privconn = vol->conn->privateData;
+    testDriverPtr privconn = volume->conn->privateData;
     virStoragePoolObjPtr privpool;
-    virStorageVolDefPtr privvol;
-    size_t i;
+    virPoolObjPtr volobj = NULL;
+    virStorageVolDefPtr voldef;
     int ret = -1;
 
     virCheckFlags(0, -1);
 
     testDriverLock(privconn);
     privpool = virStoragePoolObjFindByName(&privconn->pools,
-                                           vol->pool);
+                                           volume->pool);
     testDriverUnlock(privconn);
 
     if (privpool == NULL) {
@@ -5132,38 +5142,32 @@ testStorageVolDelete(virStorageVolPtr vol,
         goto cleanup;
     }
 
-
-    privvol = virStorageVolDefFindByName(privpool, vol->name);
-
-    if (privvol == NULL) {
-        virReportError(VIR_ERR_NO_STORAGE_VOL,
-                       _("no storage vol with matching name '%s'"),
-                       vol->name);
-        goto cleanup;
-    }
-
     if (!virStoragePoolObjIsActive(privpool)) {
         virReportError(VIR_ERR_OPERATION_INVALID,
-                       _("storage pool '%s' is not active"), vol->pool);
+                       _("storage pool '%s' is not active"), volume->pool);
         goto cleanup;
     }
 
+    if (!(volobj = virPoolObjTableFindByName(privpool->volumes,
+                                             volume->name))) {
+        virReportError(VIR_ERR_NO_STORAGE_VOL,
+                       _("no storage vol with matching name '%s'"),
+                       volume->name);
+        goto cleanup;
+    }
+    voldef = virPoolObjGetDef(volobj);
 
-    privpool->def->allocation -= privvol->target.allocation;
+    privpool->def->allocation -= voldef->target.allocation;
     privpool->def->available = (privpool->def->capacity -
                                 privpool->def->allocation);
 
-    for (i = 0; i < privpool->volumes.count; i++) {
-        if (privpool->volumes.objs[i] == privvol) {
-            virStorageVolDefFree(privvol);
 
-            VIR_DELETE_ELEMENT(privpool->volumes.objs, i, privpool->volumes.count);
-            break;
-        }
-    }
+    virStoragePoolObjRemoveVolume(privpool, &volobj);
+
     ret = 0;
 
  cleanup:
+    virPoolObjEndAPI(&volobj);
     if (privpool)
         virStoragePoolObjUnlock(privpool);
     return ret;
@@ -5184,17 +5188,18 @@ static int testStorageVolumeTypeForPool(int pooltype)
 }
 
 static int
-testStorageVolGetInfo(virStorageVolPtr vol,
+testStorageVolGetInfo(virStorageVolPtr volume,
                       virStorageVolInfoPtr info)
 {
-    testDriverPtr privconn = vol->conn->privateData;
+    testDriverPtr privconn = volume->conn->privateData;
     virStoragePoolObjPtr privpool;
-    virStorageVolDefPtr privvol;
+    virPoolObjPtr volobj = NULL;
+    virStorageVolDefPtr voldef;
     int ret = -1;
 
     testDriverLock(privconn);
     privpool = virStoragePoolObjFindByName(&privconn->pools,
-                                           vol->pool);
+                                           volume->pool);
     testDriverUnlock(privconn);
 
     if (privpool == NULL) {
@@ -5202,47 +5207,48 @@ testStorageVolGetInfo(virStorageVolPtr vol,
         goto cleanup;
     }
 
-    privvol = virStorageVolDefFindByName(privpool, vol->name);
-
-    if (privvol == NULL) {
+    if (!(volobj = virStorageVolObjFindByName(privpool, volume->name))) {
         virReportError(VIR_ERR_NO_STORAGE_VOL,
                        _("no storage vol with matching name '%s'"),
-                       vol->name);
+                       volume->name);
         goto cleanup;
     }
+    voldef = virPoolObjGetDef(volobj);
 
     if (!virStoragePoolObjIsActive(privpool)) {
         virReportError(VIR_ERR_OPERATION_INVALID,
-                       _("storage pool '%s' is not active"), vol->pool);
+                       _("storage pool '%s' is not active"), volume->pool);
         goto cleanup;
     }
 
     memset(info, 0, sizeof(*info));
     info->type = testStorageVolumeTypeForPool(privpool->def->type);
-    info->capacity = privvol->target.capacity;
-    info->allocation = privvol->target.allocation;
+    info->capacity = voldef->target.capacity;
+    info->allocation = voldef->target.allocation;
     ret = 0;
 
  cleanup:
+    virPoolObjEndAPI(&volobj);
     if (privpool)
         virStoragePoolObjUnlock(privpool);
     return ret;
 }
 
 static char *
-testStorageVolGetXMLDesc(virStorageVolPtr vol,
+testStorageVolGetXMLDesc(virStorageVolPtr volume,
                          unsigned int flags)
 {
-    testDriverPtr privconn = vol->conn->privateData;
+    testDriverPtr privconn = volume->conn->privateData;
     virStoragePoolObjPtr privpool;
-    virStorageVolDefPtr privvol;
+    virPoolObjPtr volobj = NULL;
+    virStorageVolDefPtr voldef;
     char *ret = NULL;
 
     virCheckFlags(0, NULL);
 
     testDriverLock(privconn);
     privpool = virStoragePoolObjFindByName(&privconn->pools,
-                                           vol->pool);
+                                           volume->pool);
     testDriverUnlock(privconn);
 
     if (privpool == NULL) {
@@ -5250,40 +5256,41 @@ testStorageVolGetXMLDesc(virStorageVolPtr vol,
         goto cleanup;
     }
 
-    privvol = virStorageVolDefFindByName(privpool, vol->name);
-
-    if (privvol == NULL) {
+    if (!(volobj = virStorageVolObjFindByName(privpool, volume->name))) {
         virReportError(VIR_ERR_NO_STORAGE_VOL,
                        _("no storage vol with matching name '%s'"),
-                       vol->name);
+                       volume->name);
         goto cleanup;
     }
+    voldef = virPoolObjGetDef(volobj);
 
     if (!virStoragePoolObjIsActive(privpool)) {
         virReportError(VIR_ERR_OPERATION_INVALID,
-                       _("storage pool '%s' is not active"), vol->pool);
+                       _("storage pool '%s' is not active"), volume->pool);
         goto cleanup;
     }
 
-    ret = virStorageVolDefFormat(privpool->def, privvol);
+    ret = virStorageVolDefFormat(privpool->def, voldef);
 
  cleanup:
+    virPoolObjEndAPI(&volobj);
     if (privpool)
         virStoragePoolObjUnlock(privpool);
     return ret;
 }
 
 static char *
-testStorageVolGetPath(virStorageVolPtr vol)
+testStorageVolGetPath(virStorageVolPtr volume)
 {
-    testDriverPtr privconn = vol->conn->privateData;
+    testDriverPtr privconn = volume->conn->privateData;
     virStoragePoolObjPtr privpool;
-    virStorageVolDefPtr privvol;
+    virPoolObjPtr volobj = NULL;
+    virStorageVolDefPtr voldef;
     char *ret = NULL;
 
     testDriverLock(privconn);
     privpool = virStoragePoolObjFindByName(&privconn->pools,
-                                           vol->pool);
+                                           volume->pool);
     testDriverUnlock(privconn);
 
     if (privpool == NULL) {
@@ -5291,24 +5298,24 @@ testStorageVolGetPath(virStorageVolPtr vol)
         goto cleanup;
     }
 
-    privvol = virStorageVolDefFindByName(privpool, vol->name);
-
-    if (privvol == NULL) {
+    if (!(volobj = virStorageVolObjFindByName(privpool, volume->name))) {
         virReportError(VIR_ERR_NO_STORAGE_VOL,
                        _("no storage vol with matching name '%s'"),
-                       vol->name);
+                       volume->name);
         goto cleanup;
     }
+    voldef = virPoolObjGetDef(volobj);
 
     if (!virStoragePoolObjIsActive(privpool)) {
         virReportError(VIR_ERR_OPERATION_INVALID,
-                       _("storage pool '%s' is not active"), vol->pool);
+                       _("storage pool '%s' is not active"), volume->pool);
         goto cleanup;
     }
 
-    ignore_value(VIR_STRDUP(ret, privvol->target.path));
+    ignore_value(VIR_STRDUP(ret, voldef->target.path));
 
  cleanup:
+    virPoolObjEndAPI(&volobj);
     if (privpool)
         virStoragePoolObjUnlock(privpool);
     return ret;
-- 
2.7.4




More information about the libvir-list mailing list