-struct _virStorageVolDefList {
- size_t count;
- virStorageVolDefPtr *objs;
-};
-
typedef struct _virStorageVolObj virStorageVolObj;
typedef virStorageVolObj *virStorageVolObjPtr;
struct _virStorageVolObj {
virStoragePoolDefPtr def;
virStoragePoolDefPtr newDef;
- virStorageVolDefList volumes;
+ virStorageVolObjListPtr volumes;
};
struct _virStoragePoolObjList {
VIR_ONCE_GLOBAL_INIT(virStorageVolObj)
-static virStorageVolObjPtr ATTRIBUTE_UNUSED
+static virStorageVolObjPtr
virStorageVolObjNew(void)
{
virStorageVolObjPtr obj;
}
-static void ATTRIBUTE_UNUSED
+static void
virStorageVolObjEndAPI(virStorageVolObjPtr *obj)
{
if (!*obj)
}
-static virStorageVolObjListPtr ATTRIBUTE_UNUSED
+static virStorageVolObjListPtr
virStorageVolObjListNew(void)
{
virStorageVolObjListPtr vols;
if (!(obj = virObjectLockableNew(virStoragePoolObjClass)))
return NULL;
+ if (!(obj->volumes = virStorageVolObjListNew())) {
+ virObjectUnref(obj);
+ return NULL;
+ }
+
virObjectLock(obj);
obj->active = false;
return obj;
return;
virStoragePoolObjClearVols(obj);
+ virObjectUnref(obj->volumes);
virStoragePoolDefFree(obj->def);
virStoragePoolDefFree(obj->newDef);
void
virStoragePoolObjClearVols(virStoragePoolObjPtr obj)
{
- size_t i;
- for (i = 0; i < obj->volumes.count; i++)
- virStorageVolDefFree(obj->volumes.objs[i]);
-
- VIR_FREE(obj->volumes.objs);
- obj->volumes.count = 0;
+ virHashRemoveAll(obj->volumes->objsKey);
+ virHashRemoveAll(obj->volumes->objsName);
+ virHashRemoveAll(obj->volumes->objsPath);
}
virStoragePoolObjAddVol(virStoragePoolObjPtr obj,
virStorageVolDefPtr voldef)
{
- if (VIR_APPEND_ELEMENT(obj->volumes.objs, obj->volumes.count, voldef) < 0)
- return -1;
+ virStorageVolObjPtr volobj = NULL;
+ 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;
+
+ error:
+ virStorageVolObjEndAPI(&volobj);
+ virObjectRWUnlock(volumes);
+ return -1;
}
virStoragePoolObjRemoveVol(virStoragePoolObjPtr obj,
virStorageVolDefPtr voldef)
{
- virStoragePoolDefPtr def = virStoragePoolObjGetDef(obj);
- size_t i;
-
- for (i = 0; i < obj->volumes.count; i++) {
- if (obj->volumes.objs[i] == voldef) {
- VIR_INFO("Deleting volume '%s' from storage pool '%s'",
- voldef->name, def->name);
- virStorageVolDefFree(voldef);
+ virStorageVolObjListPtr volumes = obj->volumes;
+ virStorageVolObjPtr volobj;
- VIR_DELETE_ELEMENT(obj->volumes.objs, i, obj->volumes.count);
- return;
- }
+ virObjectRWLockWrite(volumes);
+ volobj = virHashLookup(volumes->objsName, voldef->name);
+ if (!volobj) {
+ VIR_INFO("Cannot find volume '%s' from storage pool '%s'",
+ voldef->name, obj->def->name);
+ virObjectRWUnlock(volumes);
+ 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
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;
}
virStorageVolObjListIterator iter,
const void *opaque)
{
- size_t i;
-
- for (i = 0; i < obj->volumes.count; i++) {
- if (iter(obj->volumes.objs[i], opaque) < 0)
- return -1;
- }
+ struct _virStoragePoolObjForEachVolData data = {
+ .iter = iter, .opaque = opaque };
+ virObjectRWLockRead(obj->volumes);
+ virHashForEach(obj->volumes->objsKey, virStoragePoolObjForEachVolumeCb,
+ &data);
+ virObjectRWUnlock(obj->volumes);
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
virStoragePoolObjSearchVolume(virStoragePoolObjPtr obj,
virStorageVolObjListSearcher iter,
const void *opaque)
{
- size_t i;
+ virStorageVolObjPtr volobj;
+ struct _virStoragePoolObjSearchVolData data = {
+ .iter = iter, .opaque = opaque };
- for (i = 0; i < obj->volumes.count; i++) {
- if (iter(obj->volumes.objs[i], opaque))
- return obj->volumes.objs[i];
- }
+ virObjectRWLockRead(obj->volumes);
+ volobj = virHashSearch(obj->volumes->objsKey,
+ virStoragePoolObjSearchVolumeCb,
+ &data, NULL);
+ virObjectRWUnlock(obj->volumes);
+
+ if (volobj)
+ return volobj->voldef;
return NULL;
}
virStorageVolDefFindByKey(virStoragePoolObjPtr obj,
const char *key)
{
- size_t i;
+ virStorageVolObjPtr volobj;
- for (i = 0; i < obj->volumes.count; i++)
- if (STREQ(obj->volumes.objs[i]->key, key))
- return obj->volumes.objs[i];
+ virObjectRWLockRead(obj->volumes);
+ volobj = virHashLookup(obj->volumes->objsKey, key);
+ virObjectRWUnlock(obj->volumes);
+ if (volobj)
+ return volobj->voldef;
return NULL;
}
virStorageVolDefFindByPath(virStoragePoolObjPtr obj,
const char *path)
{
- size_t i;
+ virStorageVolObjPtr volobj;
- for (i = 0; i < obj->volumes.count; i++)
- if (STREQ(obj->volumes.objs[i]->target.path, path))
- return obj->volumes.objs[i];
+ virObjectRWLockRead(obj->volumes);
+ volobj = virHashLookup(obj->volumes->objsPath, path);
+ virObjectRWUnlock(obj->volumes);
+ if (volobj)
+ return volobj->voldef;
return NULL;
}
virStorageVolDefFindByName(virStoragePoolObjPtr obj,
const char *name)
{
- size_t i;
+ virStorageVolObjPtr volobj;
- for (i = 0; i < obj->volumes.count; i++)
- if (STREQ(obj->volumes.objs[i]->name, name))
- return obj->volumes.objs[i];
+ virObjectRWLockRead(obj->volumes);
+ volobj = virHashLookup(obj->volumes->objsName, name);
+ virObjectRWUnlock(obj->volumes);
+ if (volobj)
+ return volobj->voldef;
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
virStoragePoolObjNumOfVolumes(virStoragePoolObjPtr obj,
virConnectPtr conn,
virStoragePoolVolumeACLFilter filter)
{
- virStoragePoolDefPtr pooldef = obj->def;
- virStorageVolDefListPtr volumes = &obj->volumes;
- int nvolumes = 0;
- size_t i;
+ virStorageVolObjListPtr volumes = obj->volumes;
+ struct _virStorageVolObjCountData data = {
+ .conn = conn, .filter = filter, .pooldef = obj->def, .count = 0 };
- for (i = 0; i < volumes->count; i++) {
- virStorageVolDefPtr def = volumes->objs[i];
- if (filter && !filter(conn, pooldef, def))
- continue;
- nvolumes++;
+ virObjectRWLockRead(volumes);
+ virHashForEach(volumes->objsName, virStoragePoolObjNumOfVolumesCb, &data);
+ virObjectRWUnlock(volumes);
+
+ 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;
}
char **const names,
int maxnames)
{
- virStoragePoolDefPtr pooldef = obj->def;
- virStorageVolDefListPtr volumes = &obj->volumes;
- int nnames = 0;
- size_t i;
+ virStorageVolObjListPtr volumes = obj->volumes;
+ struct _virStorageVolObjNameData data = {
+ .conn = conn, .filter = filter, .pooldef = obj->def, .error = false,
+ .nnames = 0, .maxnames = maxnames, .names = names };
- for (i = 0; i < volumes->count && nnames < maxnames; i++) {
- virStorageVolDefPtr def = volumes->objs[i];
- if (filter && !filter(conn, pooldef, def))
- continue;
- if (VIR_STRDUP(names[nnames], def->name) < 0)
- goto failure;
- nnames++;
- }
+ virObjectRWLockRead(volumes);
+ virHashForEach(volumes->objsName, virStoragePoolObjVolumeGetNamesCb, &data);
+ virObjectRWUnlock(volumes);
- return nnames;
+ if (data.error)
+ goto error;
- failure:
- while (--nnames >= 0)
- VIR_FREE(names[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;
+ }
+
+ data->nvols++;
+
+ cleanup:
+ virObjectUnlock(volobj);
+ return 0;
+}
+
+
int
virStoragePoolObjVolumeListExport(virConnectPtr conn,
virStoragePoolObjPtr obj,
virStorageVolPtr **vols,
virStoragePoolVolumeACLFilter filter)
{
- virStoragePoolDefPtr pooldef = obj->def;
- virStorageVolDefListPtr volumes = &obj->volumes;
- int ret = -1;
- size_t i;
- virStorageVolPtr *tmp_vols = NULL;
- virStorageVolPtr vol = NULL;
- int nvols = 0;
+ virStorageVolObjListPtr volumes = obj->volumes;
+ struct _virStorageVolObjExportData data = {
+ .conn = conn, .filter = filter, .pooldef = obj->def, .error = false,
+ .nvols = 0, .vols = NULL };
+
+ virObjectRWLockRead(volumes);
- /* Just returns the volumes count */
if (!vols) {
- ret = volumes->count;
- goto cleanup;
+ int ret = virHashSize(volumes->objsName);
+ virObjectRWUnlock(volumes);
+ return ret;
}
- if (VIR_ALLOC_N(tmp_vols, volumes->count + 1) < 0)
- goto cleanup;
-
- 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;
+ if (VIR_ALLOC_N(data.vols, virHashSize(volumes->objsName) + 1) < 0) {
+ virObjectRWUnlock(volumes);
+ return -1;
}
- *vols = tmp_vols;
- tmp_vols = NULL;
- ret = nvols;
+ virHashForEach(volumes->objsName, virStoragePoolObjVolumeListExportCb, &data);
+ virObjectRWUnlock(volumes);
- cleanup:
- if (tmp_vols) {
- for (i = 0; i < nvols; i++)
- virObjectUnref(tmp_vols[i]);
- VIR_FREE(tmp_vols);
- }
+ if (data.error)
+ goto error;
- return ret;
+ *vols = data.vols;
+
+ return data.nvols;
+
+ error:
+ virObjectListFree(data.vols);
+ return -1;
}