mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-09-08 16:54:49 +00:00
storage: Complete implementation volume by hash object
Alter the volume logic to use the hash tables instead of forward linked lists. There are three hash tables to allow for fast lookup by name, target.path, and key. Modify the virStoragePoolObjAddVol to place the object in all 3 tables if possible using self locking RWLock on the volumes object. Conversely when removing the volume, it's a removal of the object from the various hash tables. Implement functions to handle remote ForEach and Search Volume type helpers. These are used by the disk backend in order to facilitate adding a primary, extended, or logical partition. Implement the various VolDefFindBy* helpers as simple (and fast) hash lookups. The NumOfVolumes, GetNames, and ListExport helpers are all implemented using standard for each hash table calls.
This commit is contained in:
parent
f77c898d1e
commit
be1bb6c95b
@ -53,11 +53,6 @@ virStorageVolObjListDispose(void *opaque);
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct _virStorageVolDefList {
|
|
||||||
size_t count;
|
|
||||||
virStorageVolDefPtr *objs;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct _virStorageVolObj virStorageVolObj;
|
typedef struct _virStorageVolObj virStorageVolObj;
|
||||||
typedef virStorageVolObj *virStorageVolObjPtr;
|
typedef virStorageVolObj *virStorageVolObjPtr;
|
||||||
struct _virStorageVolObj {
|
struct _virStorageVolObj {
|
||||||
@ -96,7 +91,7 @@ struct _virStoragePoolObj {
|
|||||||
virStoragePoolDefPtr def;
|
virStoragePoolDefPtr def;
|
||||||
virStoragePoolDefPtr newDef;
|
virStoragePoolDefPtr newDef;
|
||||||
|
|
||||||
virStorageVolDefList volumes;
|
virStorageVolObjListPtr volumes;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _virStoragePoolObjList {
|
struct _virStoragePoolObjList {
|
||||||
@ -133,7 +128,7 @@ virStorageVolObjOnceInit(void)
|
|||||||
VIR_ONCE_GLOBAL_INIT(virStorageVolObj)
|
VIR_ONCE_GLOBAL_INIT(virStorageVolObj)
|
||||||
|
|
||||||
|
|
||||||
static virStorageVolObjPtr ATTRIBUTE_UNUSED
|
static virStorageVolObjPtr
|
||||||
virStorageVolObjNew(void)
|
virStorageVolObjNew(void)
|
||||||
{
|
{
|
||||||
virStorageVolObjPtr obj;
|
virStorageVolObjPtr obj;
|
||||||
@ -149,7 +144,7 @@ virStorageVolObjNew(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void ATTRIBUTE_UNUSED
|
static void
|
||||||
virStorageVolObjEndAPI(virStorageVolObjPtr *obj)
|
virStorageVolObjEndAPI(virStorageVolObjPtr *obj)
|
||||||
{
|
{
|
||||||
if (!*obj)
|
if (!*obj)
|
||||||
@ -173,7 +168,7 @@ virStorageVolObjDispose(void *opaque)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static virStorageVolObjListPtr ATTRIBUTE_UNUSED
|
static virStorageVolObjListPtr
|
||||||
virStorageVolObjListNew(void)
|
virStorageVolObjListNew(void)
|
||||||
{
|
{
|
||||||
virStorageVolObjListPtr vols;
|
virStorageVolObjListPtr vols;
|
||||||
@ -241,6 +236,11 @@ virStoragePoolObjNew(void)
|
|||||||
if (!(obj = virObjectLockableNew(virStoragePoolObjClass)))
|
if (!(obj = virObjectLockableNew(virStoragePoolObjClass)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
if (!(obj->volumes = virStorageVolObjListNew())) {
|
||||||
|
virObjectUnref(obj);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
virObjectLock(obj);
|
virObjectLock(obj);
|
||||||
obj->active = false;
|
obj->active = false;
|
||||||
return obj;
|
return obj;
|
||||||
@ -377,6 +377,7 @@ virStoragePoolObjDispose(void *opaque)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
virStoragePoolObjClearVols(obj);
|
virStoragePoolObjClearVols(obj);
|
||||||
|
virObjectUnref(obj->volumes);
|
||||||
|
|
||||||
virStoragePoolDefFree(obj->def);
|
virStoragePoolDefFree(obj->def);
|
||||||
virStoragePoolDefFree(obj->newDef);
|
virStoragePoolDefFree(obj->newDef);
|
||||||
@ -625,12 +626,9 @@ virStoragePoolSourceFindDuplicateDevices(virStoragePoolObjPtr obj,
|
|||||||
void
|
void
|
||||||
virStoragePoolObjClearVols(virStoragePoolObjPtr obj)
|
virStoragePoolObjClearVols(virStoragePoolObjPtr obj)
|
||||||
{
|
{
|
||||||
size_t i;
|
virHashRemoveAll(obj->volumes->objsKey);
|
||||||
for (i = 0; i < obj->volumes.count; i++)
|
virHashRemoveAll(obj->volumes->objsName);
|
||||||
virStorageVolDefFree(obj->volumes.objs[i]);
|
virHashRemoveAll(obj->volumes->objsPath);
|
||||||
|
|
||||||
VIR_FREE(obj->volumes.objs);
|
|
||||||
obj->volumes.count = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -638,9 +636,40 @@ int
|
|||||||
virStoragePoolObjAddVol(virStoragePoolObjPtr obj,
|
virStoragePoolObjAddVol(virStoragePoolObjPtr obj,
|
||||||
virStorageVolDefPtr voldef)
|
virStorageVolDefPtr voldef)
|
||||||
{
|
{
|
||||||
if (VIR_APPEND_ELEMENT(obj->volumes.objs, obj->volumes.count, voldef) < 0)
|
virStorageVolObjPtr volobj = NULL;
|
||||||
return -1;
|
virStorageVolObjListPtr volumes = obj->volumes;
|
||||||
|
|
||||||
|
virObjectRWLockWrite(volumes);
|
||||||
|
|
||||||
|
if (!(volobj = virStorageVolObjNew()))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (virHashAddEntry(volumes->objsKey, voldef->key, volobj) < 0)
|
||||||
|
goto error;
|
||||||
|
virObjectRef(volobj);
|
||||||
|
|
||||||
|
if (virHashAddEntry(volumes->objsName, voldef->name, volobj) < 0) {
|
||||||
|
virHashRemoveEntry(volumes->objsKey, voldef->key);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
virObjectRef(volobj);
|
||||||
|
|
||||||
|
if (virHashAddEntry(volumes->objsPath, voldef->target.path, volobj) < 0) {
|
||||||
|
virHashRemoveEntry(volumes->objsKey, voldef->key);
|
||||||
|
virHashRemoveEntry(volumes->objsName, voldef->name);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
virObjectRef(volobj);
|
||||||
|
|
||||||
|
volobj->voldef = voldef;
|
||||||
|
virObjectRWUnlock(volumes);
|
||||||
|
virStorageVolObjEndAPI(&volobj);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
virStorageVolObjEndAPI(&volobj);
|
||||||
|
virObjectRWUnlock(volumes);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -648,26 +677,64 @@ void
|
|||||||
virStoragePoolObjRemoveVol(virStoragePoolObjPtr obj,
|
virStoragePoolObjRemoveVol(virStoragePoolObjPtr obj,
|
||||||
virStorageVolDefPtr voldef)
|
virStorageVolDefPtr voldef)
|
||||||
{
|
{
|
||||||
virStoragePoolDefPtr def = virStoragePoolObjGetDef(obj);
|
virStorageVolObjListPtr volumes = obj->volumes;
|
||||||
size_t i;
|
virStorageVolObjPtr volobj;
|
||||||
|
|
||||||
for (i = 0; i < obj->volumes.count; i++) {
|
virObjectRWLockWrite(volumes);
|
||||||
if (obj->volumes.objs[i] == voldef) {
|
volobj = virHashLookup(volumes->objsName, voldef->name);
|
||||||
VIR_INFO("Deleting volume '%s' from storage pool '%s'",
|
if (!volobj) {
|
||||||
voldef->name, def->name);
|
VIR_INFO("Cannot find volume '%s' from storage pool '%s'",
|
||||||
virStorageVolDefFree(voldef);
|
voldef->name, obj->def->name);
|
||||||
|
virObjectRWUnlock(volumes);
|
||||||
VIR_DELETE_ELEMENT(obj->volumes.objs, i, obj->volumes.count);
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
VIR_INFO("Deleting volume '%s' from storage pool '%s'",
|
||||||
|
voldef->name, obj->def->name);
|
||||||
|
|
||||||
|
virObjectRef(volobj);
|
||||||
|
virObjectLock(volobj);
|
||||||
|
virHashRemoveEntry(volumes->objsKey, voldef->key);
|
||||||
|
virHashRemoveEntry(volumes->objsName, voldef->name);
|
||||||
|
virHashRemoveEntry(volumes->objsPath, voldef->target.path);
|
||||||
|
virStorageVolObjEndAPI(&volobj);
|
||||||
|
|
||||||
|
virObjectRWUnlock(volumes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
virStoragePoolObjGetVolumesCount(virStoragePoolObjPtr obj)
|
virStoragePoolObjGetVolumesCount(virStoragePoolObjPtr obj)
|
||||||
{
|
{
|
||||||
return obj->volumes.count;
|
size_t nbElems;
|
||||||
|
|
||||||
|
virObjectRWLockRead(obj->volumes);
|
||||||
|
nbElems = virHashSize(obj->volumes->objsKey);
|
||||||
|
virObjectRWUnlock(obj->volumes);
|
||||||
|
|
||||||
|
return nbElems;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct _virStoragePoolObjForEachVolData {
|
||||||
|
virStorageVolObjListIterator iter;
|
||||||
|
const void *opaque;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
virStoragePoolObjForEachVolumeCb(void *payload,
|
||||||
|
const void *name ATTRIBUTE_UNUSED,
|
||||||
|
void *opaque)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
virStorageVolObjPtr volobj = payload;
|
||||||
|
struct _virStoragePoolObjForEachVolData *data = opaque;
|
||||||
|
|
||||||
|
virObjectLock(volobj);
|
||||||
|
if (data->iter(volobj->voldef, data->opaque) < 0)
|
||||||
|
ret = -1;
|
||||||
|
virObjectUnlock(volobj);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -676,28 +743,58 @@ virStoragePoolObjForEachVolume(virStoragePoolObjPtr obj,
|
|||||||
virStorageVolObjListIterator iter,
|
virStorageVolObjListIterator iter,
|
||||||
const void *opaque)
|
const void *opaque)
|
||||||
{
|
{
|
||||||
size_t i;
|
struct _virStoragePoolObjForEachVolData data = {
|
||||||
|
.iter = iter, .opaque = opaque };
|
||||||
for (i = 0; i < obj->volumes.count; i++) {
|
|
||||||
if (iter(obj->volumes.objs[i], opaque) < 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
virObjectRWLockRead(obj->volumes);
|
||||||
|
virHashForEach(obj->volumes->objsKey, virStoragePoolObjForEachVolumeCb,
|
||||||
|
&data);
|
||||||
|
virObjectRWUnlock(obj->volumes);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct _virStoragePoolObjSearchVolData {
|
||||||
|
virStorageVolObjListSearcher iter;
|
||||||
|
const void *opaque;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
virStoragePoolObjSearchVolumeCb(const void *payload,
|
||||||
|
const void *name ATTRIBUTE_UNUSED,
|
||||||
|
const void *opaque)
|
||||||
|
{
|
||||||
|
virStorageVolObjPtr volobj = (virStorageVolObjPtr) payload;
|
||||||
|
struct _virStoragePoolObjSearchVolData *data =
|
||||||
|
(struct _virStoragePoolObjSearchVolData *) opaque;
|
||||||
|
int found = 0;
|
||||||
|
|
||||||
|
virObjectLock(volobj);
|
||||||
|
if (data->iter(volobj->voldef, data->opaque))
|
||||||
|
found = 1;
|
||||||
|
virObjectUnlock(volobj);
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
virStorageVolDefPtr
|
virStorageVolDefPtr
|
||||||
virStoragePoolObjSearchVolume(virStoragePoolObjPtr obj,
|
virStoragePoolObjSearchVolume(virStoragePoolObjPtr obj,
|
||||||
virStorageVolObjListSearcher iter,
|
virStorageVolObjListSearcher iter,
|
||||||
const void *opaque)
|
const void *opaque)
|
||||||
{
|
{
|
||||||
size_t i;
|
virStorageVolObjPtr volobj;
|
||||||
|
struct _virStoragePoolObjSearchVolData data = {
|
||||||
|
.iter = iter, .opaque = opaque };
|
||||||
|
|
||||||
for (i = 0; i < obj->volumes.count; i++) {
|
virObjectRWLockRead(obj->volumes);
|
||||||
if (iter(obj->volumes.objs[i], opaque))
|
volobj = virHashSearch(obj->volumes->objsKey,
|
||||||
return obj->volumes.objs[i];
|
virStoragePoolObjSearchVolumeCb,
|
||||||
}
|
&data, NULL);
|
||||||
|
virObjectRWUnlock(obj->volumes);
|
||||||
|
|
||||||
|
if (volobj)
|
||||||
|
return volobj->voldef;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -707,12 +804,14 @@ virStorageVolDefPtr
|
|||||||
virStorageVolDefFindByKey(virStoragePoolObjPtr obj,
|
virStorageVolDefFindByKey(virStoragePoolObjPtr obj,
|
||||||
const char *key)
|
const char *key)
|
||||||
{
|
{
|
||||||
size_t i;
|
virStorageVolObjPtr volobj;
|
||||||
|
|
||||||
for (i = 0; i < obj->volumes.count; i++)
|
virObjectRWLockRead(obj->volumes);
|
||||||
if (STREQ(obj->volumes.objs[i]->key, key))
|
volobj = virHashLookup(obj->volumes->objsKey, key);
|
||||||
return obj->volumes.objs[i];
|
virObjectRWUnlock(obj->volumes);
|
||||||
|
|
||||||
|
if (volobj)
|
||||||
|
return volobj->voldef;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -721,12 +820,14 @@ virStorageVolDefPtr
|
|||||||
virStorageVolDefFindByPath(virStoragePoolObjPtr obj,
|
virStorageVolDefFindByPath(virStoragePoolObjPtr obj,
|
||||||
const char *path)
|
const char *path)
|
||||||
{
|
{
|
||||||
size_t i;
|
virStorageVolObjPtr volobj;
|
||||||
|
|
||||||
for (i = 0; i < obj->volumes.count; i++)
|
virObjectRWLockRead(obj->volumes);
|
||||||
if (STREQ(obj->volumes.objs[i]->target.path, path))
|
volobj = virHashLookup(obj->volumes->objsPath, path);
|
||||||
return obj->volumes.objs[i];
|
virObjectRWUnlock(obj->volumes);
|
||||||
|
|
||||||
|
if (volobj)
|
||||||
|
return volobj->voldef;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -735,34 +836,107 @@ virStorageVolDefPtr
|
|||||||
virStorageVolDefFindByName(virStoragePoolObjPtr obj,
|
virStorageVolDefFindByName(virStoragePoolObjPtr obj,
|
||||||
const char *name)
|
const char *name)
|
||||||
{
|
{
|
||||||
size_t i;
|
virStorageVolObjPtr volobj;
|
||||||
|
|
||||||
for (i = 0; i < obj->volumes.count; i++)
|
virObjectRWLockRead(obj->volumes);
|
||||||
if (STREQ(obj->volumes.objs[i]->name, name))
|
volobj = virHashLookup(obj->volumes->objsName, name);
|
||||||
return obj->volumes.objs[i];
|
virObjectRWUnlock(obj->volumes);
|
||||||
|
|
||||||
|
if (volobj)
|
||||||
|
return volobj->voldef;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct _virStorageVolObjCountData {
|
||||||
|
virConnectPtr conn;
|
||||||
|
virStoragePoolVolumeACLFilter filter;
|
||||||
|
virStoragePoolDefPtr pooldef;
|
||||||
|
int count;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
virStoragePoolObjNumOfVolumesCb(void *payload,
|
||||||
|
const void *name ATTRIBUTE_UNUSED,
|
||||||
|
void *opaque)
|
||||||
|
{
|
||||||
|
virStorageVolObjPtr volobj = payload;
|
||||||
|
struct _virStorageVolObjCountData *data = opaque;
|
||||||
|
|
||||||
|
virObjectLock(volobj);
|
||||||
|
|
||||||
|
if (data->filter &&
|
||||||
|
!data->filter(data->conn, data->pooldef, volobj->voldef))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
data->count++;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
virObjectUnlock(volobj);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
virStoragePoolObjNumOfVolumes(virStoragePoolObjPtr obj,
|
virStoragePoolObjNumOfVolumes(virStoragePoolObjPtr obj,
|
||||||
virConnectPtr conn,
|
virConnectPtr conn,
|
||||||
virStoragePoolVolumeACLFilter filter)
|
virStoragePoolVolumeACLFilter filter)
|
||||||
{
|
{
|
||||||
virStoragePoolDefPtr pooldef = obj->def;
|
virStorageVolObjListPtr volumes = obj->volumes;
|
||||||
virStorageVolDefListPtr volumes = &obj->volumes;
|
struct _virStorageVolObjCountData data = {
|
||||||
int nvolumes = 0;
|
.conn = conn, .filter = filter, .pooldef = obj->def, .count = 0 };
|
||||||
size_t i;
|
|
||||||
|
|
||||||
for (i = 0; i < volumes->count; i++) {
|
virObjectRWLockRead(volumes);
|
||||||
virStorageVolDefPtr def = volumes->objs[i];
|
virHashForEach(volumes->objsName, virStoragePoolObjNumOfVolumesCb, &data);
|
||||||
if (filter && !filter(conn, pooldef, def))
|
virObjectRWUnlock(volumes);
|
||||||
continue;
|
|
||||||
nvolumes++;
|
return data.count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct _virStorageVolObjNameData {
|
||||||
|
virConnectPtr conn;
|
||||||
|
virStoragePoolVolumeACLFilter filter;
|
||||||
|
virStoragePoolDefPtr pooldef;
|
||||||
|
bool error;
|
||||||
|
int nnames;
|
||||||
|
int maxnames;
|
||||||
|
char **const names;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
virStoragePoolObjVolumeGetNamesCb(void *payload,
|
||||||
|
const void *name ATTRIBUTE_UNUSED,
|
||||||
|
void *opaque)
|
||||||
|
{
|
||||||
|
virStorageVolObjPtr volobj = payload;
|
||||||
|
struct _virStorageVolObjNameData *data = opaque;
|
||||||
|
|
||||||
|
if (data->error)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (data->maxnames >= 0 && data->nnames == data->maxnames)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
virObjectLock(volobj);
|
||||||
|
|
||||||
|
if (data->filter &&
|
||||||
|
!data->filter(data->conn, data->pooldef, volobj->voldef))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (data->names) {
|
||||||
|
if (VIR_STRDUP(data->names[data->nnames], volobj->voldef->name) < 0) {
|
||||||
|
data->error = true;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nvolumes;
|
data->nnames++;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
virObjectUnlock(volobj);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -773,27 +947,69 @@ virStoragePoolObjVolumeGetNames(virStoragePoolObjPtr obj,
|
|||||||
char **const names,
|
char **const names,
|
||||||
int maxnames)
|
int maxnames)
|
||||||
{
|
{
|
||||||
virStoragePoolDefPtr pooldef = obj->def;
|
virStorageVolObjListPtr volumes = obj->volumes;
|
||||||
virStorageVolDefListPtr volumes = &obj->volumes;
|
struct _virStorageVolObjNameData data = {
|
||||||
int nnames = 0;
|
.conn = conn, .filter = filter, .pooldef = obj->def, .error = false,
|
||||||
size_t i;
|
.nnames = 0, .maxnames = maxnames, .names = names };
|
||||||
|
|
||||||
for (i = 0; i < volumes->count && nnames < maxnames; i++) {
|
virObjectRWLockRead(volumes);
|
||||||
virStorageVolDefPtr def = volumes->objs[i];
|
virHashForEach(volumes->objsName, virStoragePoolObjVolumeGetNamesCb, &data);
|
||||||
if (filter && !filter(conn, pooldef, def))
|
virObjectRWUnlock(volumes);
|
||||||
continue;
|
|
||||||
if (VIR_STRDUP(names[nnames], def->name) < 0)
|
if (data.error)
|
||||||
goto failure;
|
goto error;
|
||||||
nnames++;
|
|
||||||
|
return data.nnames;
|
||||||
|
|
||||||
|
error:
|
||||||
|
while (--data.nnames)
|
||||||
|
VIR_FREE(data.names[data.nnames]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct _virStorageVolObjExportData {
|
||||||
|
virConnectPtr conn;
|
||||||
|
virStoragePoolVolumeACLFilter filter;
|
||||||
|
virStoragePoolDefPtr pooldef;
|
||||||
|
bool error;
|
||||||
|
int nvols;
|
||||||
|
virStorageVolPtr *vols;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
virStoragePoolObjVolumeListExportCb(void *payload,
|
||||||
|
const void *name ATTRIBUTE_UNUSED,
|
||||||
|
void *opaque)
|
||||||
|
{
|
||||||
|
virStorageVolObjPtr volobj = payload;
|
||||||
|
struct _virStorageVolObjExportData *data = opaque;
|
||||||
|
virStorageVolPtr vol = NULL;
|
||||||
|
|
||||||
|
if (data->error)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
virObjectLock(volobj);
|
||||||
|
|
||||||
|
if (data->filter &&
|
||||||
|
!data->filter(data->conn, data->pooldef, volobj->voldef))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (data->vols) {
|
||||||
|
if (!(vol = virGetStorageVol(data->conn, data->pooldef->name,
|
||||||
|
volobj->voldef->name, volobj->voldef->key,
|
||||||
|
NULL, NULL))) {
|
||||||
|
data->error = true;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
data->vols[data->nvols] = vol;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nnames;
|
data->nvols++;
|
||||||
|
|
||||||
failure:
|
cleanup:
|
||||||
while (--nnames >= 0)
|
virObjectUnlock(volobj);
|
||||||
VIR_FREE(names[nnames]);
|
return 0;
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -803,45 +1019,37 @@ virStoragePoolObjVolumeListExport(virConnectPtr conn,
|
|||||||
virStorageVolPtr **vols,
|
virStorageVolPtr **vols,
|
||||||
virStoragePoolVolumeACLFilter filter)
|
virStoragePoolVolumeACLFilter filter)
|
||||||
{
|
{
|
||||||
virStoragePoolDefPtr pooldef = obj->def;
|
virStorageVolObjListPtr volumes = obj->volumes;
|
||||||
virStorageVolDefListPtr volumes = &obj->volumes;
|
struct _virStorageVolObjExportData data = {
|
||||||
int ret = -1;
|
.conn = conn, .filter = filter, .pooldef = obj->def, .error = false,
|
||||||
size_t i;
|
.nvols = 0, .vols = NULL };
|
||||||
virStorageVolPtr *tmp_vols = NULL;
|
|
||||||
virStorageVolPtr vol = NULL;
|
virObjectRWLockRead(volumes);
|
||||||
int nvols = 0;
|
|
||||||
|
|
||||||
/* Just returns the volumes count */
|
|
||||||
if (!vols) {
|
if (!vols) {
|
||||||
ret = volumes->count;
|
int ret = virHashSize(volumes->objsName);
|
||||||
goto cleanup;
|
virObjectRWUnlock(volumes);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (VIR_ALLOC_N(tmp_vols, volumes->count + 1) < 0)
|
if (VIR_ALLOC_N(data.vols, virHashSize(volumes->objsName) + 1) < 0) {
|
||||||
goto cleanup;
|
virObjectRWUnlock(volumes);
|
||||||
|
return -1;
|
||||||
for (i = 0; i < volumes->count; i++) {
|
|
||||||
virStorageVolDefPtr def = volumes->objs[i];
|
|
||||||
if (filter && !filter(conn, pooldef, def))
|
|
||||||
continue;
|
|
||||||
if (!(vol = virGetStorageVol(conn, pooldef->name, def->name, def->key,
|
|
||||||
NULL, NULL)))
|
|
||||||
goto cleanup;
|
|
||||||
tmp_vols[nvols++] = vol;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*vols = tmp_vols;
|
virHashForEach(volumes->objsName, virStoragePoolObjVolumeListExportCb, &data);
|
||||||
tmp_vols = NULL;
|
virObjectRWUnlock(volumes);
|
||||||
ret = nvols;
|
|
||||||
|
|
||||||
cleanup:
|
if (data.error)
|
||||||
if (tmp_vols) {
|
goto error;
|
||||||
for (i = 0; i < nvols; i++)
|
|
||||||
virObjectUnref(tmp_vols[i]);
|
|
||||||
VIR_FREE(tmp_vols);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
*vols = data.vols;
|
||||||
|
|
||||||
|
return data.nvols;
|
||||||
|
|
||||||
|
error:
|
||||||
|
virObjectListFree(data.vols);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user