Signed-off-by: Olga Krishtal <okrishtal(a)virtuozzo.com>
---
src/fs/fs_driver.c | 1723 +++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 1515 insertions(+), 208 deletions(-)
diff --git a/src/fs/fs_driver.c b/src/fs/fs_driver.c
index 98d91fa..f913ce5 100644
--- a/src/fs/fs_driver.c
+++ b/src/fs/fs_driver.c
@@ -82,314 +82,1621 @@ virFSBackendForType(int type)
}
/* General fspool/item implementation */
+
static int
-fsConnectListAllFSPools(virConnectPtr conn ATTRIBUTE_UNUSED,
- virFSPoolPtr **fspools ATTRIBUTE_UNUSED,
+fsConnectListAllFSPools(virConnectPtr conn,
+ virFSPoolPtr **fspools,
unsigned int flags)
{
- virCheckFlags(0, -1);
+ int ret = -1;
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("the operation is not yet supported"));
+ virCheckFlags(VIR_CONNECT_LIST_FSPOOLS_FILTERS_ALL, -1);
+
+ if (virConnectListAllFSPoolsEnsureACL(conn) < 0)
+ goto cleanup;
+
+ fsDriverLock();
+ ret = virFSPoolObjListExport(conn, driver->fspools, fspools,
+ virConnectListAllFSPoolsCheckACL,
+ flags);
+ fsDriverUnlock();
+
+ cleanup:
+ return ret;
- return -1;
}
static virFSPoolPtr
-fsPoolLookupByName(virConnectPtr conn ATTRIBUTE_UNUSED,
- const char *name ATTRIBUTE_UNUSED)
+fsPoolLookupByName(virConnectPtr conn,
+ const char *name)
{
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("the operation is not yet supported"));
+ virFSPoolObjPtr fspool;
+ virFSPoolPtr ret = NULL;
- return NULL;
+ fsDriverLock();
+ fspool = virFSPoolObjFindByName(&driver->fspools, name);
+ fsDriverUnlock();
+
+ if (!fspool) {
+ virReportError(VIR_ERR_NO_FSPOOL,
+ _("no fspool with matching name '%s'"), name);
+ return NULL;
+ }
+
+ if (virFSPoolLookupByNameEnsureACL(conn, fspool->def) < 0)
+ goto cleanup;
+
+ ret = virGetFSPool(conn, fspool->def->name, fspool->def->uuid,
+ NULL, NULL);
+
+ cleanup:
+ virFSPoolObjUnlock(fspool);
+ return ret;
}
static virFSPoolPtr
-fsPoolLookupByUUID(virConnectPtr conn ATTRIBUTE_UNUSED,
- const unsigned char *uuid ATTRIBUTE_UNUSED)
+fsPoolLookupByUUID(virConnectPtr conn,
+ const unsigned char *uuid)
{
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("the operation is not yet supported"));
+ virFSPoolObjPtr fspool;
+ virFSPoolPtr ret = NULL;
- return NULL;
+ fsDriverLock();
+ fspool = virFSPoolObjFindByUUID(&driver->fspools, uuid);
+ fsDriverUnlock();
+
+ if (!fspool) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(uuid, uuidstr);
+ virReportError(VIR_ERR_NO_FSPOOL,
+ _("no fspool with matching uuid '%s'"),
uuidstr);
+ return NULL;
+ }
+
+ if (virFSPoolLookupByUUIDEnsureACL(conn, fspool->def) < 0)
+ goto cleanup;
+
+ ret = virGetFSPool(conn, fspool->def->name, fspool->def->uuid,
+ NULL, NULL);
+
+ cleanup:
+ virFSPoolObjUnlock(fspool);
+ return ret;
}
static virFSPoolPtr
-fsPoolLookupByItem(virFSItemPtr item ATTRIBUTE_UNUSED)
+fsPoolLookupByItem(virFSItemPtr item)
{
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("the operation is not yet supported"));
+ virFSPoolObjPtr fspool;
+ virFSPoolPtr ret = NULL;
- return NULL;
+ fsDriverLock();
+ fspool = virFSPoolObjFindByName(&driver->fspools, item->pool);
+ fsDriverUnlock();
+
+ if (!fspool) {
+ virReportError(VIR_ERR_NO_FSPOOL,
+ _("no fspool with matching name '%s'"),
+ item->pool);
+ return NULL;
+ }
+
+ if (virFSPoolLookupByItemEnsureACL(item->conn, fspool->def) < 0)
+ goto cleanup;
+
+ ret = virGetFSPool(item->conn, fspool->def->name, fspool->def->uuid,
+ NULL, NULL);
+
+ cleanup:
+ virFSPoolObjUnlock(fspool);
+ return ret;
}
static virFSPoolPtr
-fsPoolCreateXML(virConnectPtr conn ATTRIBUTE_UNUSED,
- const char *xml ATTRIBUTE_UNUSED,
+fsPoolCreateXML(virConnectPtr conn,
+ const char *xml,
unsigned int flags)
{
- virCheckFlags(0, NULL);
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("the operation is not yet supported"));
+ virFSPoolDefPtr def;
+ virFSPoolObjPtr fspool = NULL;
+ virFSPoolPtr ret = NULL;
+ virFSBackendPtr backend;
+ char *stateFile = NULL;
+ unsigned int build_flags = 0;
- return NULL;
+ virCheckFlags(VIR_FSPOOL_CREATE_WITH_BUILD_OVERWRITE |
+ VIR_FSPOOL_CREATE_WITH_BUILD_NO_OVERWRITE, NULL);
+
+ VIR_EXCLUSIVE_FLAGS_RET(VIR_FSPOOL_BUILD_OVERWRITE,
+ VIR_FSPOOL_BUILD_NO_OVERWRITE, NULL);
+
+ fsDriverLock();
+ if (!(def = virFSPoolDefParseString(xml)))
+ goto cleanup;
+
+ if (virFSPoolCreateXMLEnsureACL(conn, def) < 0)
+ goto cleanup;
+
+ if (virFSPoolObjIsDuplicate(&driver->fspools, def, 1) < 0)
+ goto cleanup;
+
+ if (virFSPoolSourceFindDuplicate(conn, &driver->fspools, def) < 0)
+ goto cleanup;
+
+ if ((backend = virFSBackendForType(def->type)) == NULL)
+ goto cleanup;
+
+ if (!(fspool = virFSPoolObjAssignDef(&driver->fspools, def)))
+ goto cleanup;
+ def = NULL;
+
+ if (backend->buildFSpool) {
+ if (flags & VIR_FSPOOL_CREATE_WITH_BUILD_OVERWRITE)
+ build_flags |= VIR_FSPOOL_BUILD_OVERWRITE;
+ else if (flags & VIR_FSPOOL_CREATE_WITH_BUILD_NO_OVERWRITE)
+ build_flags |= VIR_FSPOOL_BUILD_NO_OVERWRITE;
+
+ if (backend->buildFSpool(conn, fspool, build_flags) < 0) {
+ virFSPoolObjRemove(&driver->fspools, fspool);
+ fspool = NULL;
+ goto cleanup;
+ }
+ }
+
+ if (backend->startFSpool &&
+ backend->startFSpool(conn, fspool) < 0) {
+ virFSPoolObjRemove(&driver->fspools, fspool);
+ fspool = NULL;
+ goto cleanup;
+ }
+
+ stateFile = virFileBuildPath(driver->stateDir,
+ fspool->def->name, ".xml");
+
+ if (!stateFile || virFSPoolSaveState(stateFile, fspool->def) < 0 ||
+ backend->refreshFSpool(conn, fspool) < 0) {
+ if (stateFile)
+ unlink(stateFile);
+ if (backend->stopFSpool)
+ backend->stopFSpool(conn, fspool);
+ virFSPoolObjRemove(&driver->fspools, fspool);
+ fspool = NULL;
+ goto cleanup;
+ }
+ VIR_INFO("Creating fspool '%s'", fspool->def->name);
+ fspool->active = true;
+
+ ret = virGetFSPool(conn, fspool->def->name, fspool->def->uuid,
+ NULL, NULL);
+
+ cleanup:
+ VIR_FREE(stateFile);
+ virStoragePoolDefFree(def);
+ if (fspool)
+ virFSPoolObjUnlock(fspool);
+ fsDriverUnlock();
+ return ret;
}
static virFSPoolPtr
-fsPoolDefineXML(virConnectPtr conn ATTRIBUTE_UNUSED,
- const char *xml ATTRIBUTE_UNUSED,
+fsPoolDefineXML(virConnectPtr conn,
+ const char *xml,
unsigned int flags)
{
+ virFSPoolDefPtr def;
+ virFSPoolObjPtr fspool = NULL;
+ virFSPoolPtr ret = NULL;
+
virCheckFlags(0, NULL);
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("the operation is not yet supported"));
- return NULL;
-}
+ fsDriverLock();
+ if (!(def = virFSPoolDefParseString(xml)))
+ goto cleanup;
-static int
-fsPoolCreate(virFSPoolPtr obj ATTRIBUTE_UNUSED,
- unsigned int flags)
-{
- virCheckFlags(0, -1);
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("the operation is not yet supported"));
+ if (virFSPoolDefineXMLEnsureACL(conn, def) < 0)
+ goto cleanup;
- return -1;
-}
+ if (virFSPoolObjIsDuplicate(&driver->fspools, def, 0) < 0)
+ goto cleanup;
-static int
-fsPoolBuild(virFSPoolPtr obj ATTRIBUTE_UNUSED,
- unsigned int flags)
-{
- virCheckFlags(0, -1);
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("the operation is not yet supported"));
+ if (virFSPoolSourceFindDuplicate(conn, &driver->fspools, def) < 0)
+ goto cleanup;
- return -1;
-}
+ if (virFSBackendForType(def->type) == NULL)
+ goto cleanup;
-static int
-fsPoolUndefine(virFSPoolPtr obj ATTRIBUTE_UNUSED)
-{
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("the operation is not yet supported"));
+ if (!(fspool = virFSPoolObjAssignDef(&driver->fspools, def)))
+ goto cleanup;
- return -1;
-}
+ if (virFSPoolObjSaveDef(driver, fspool, def) < 0) {
+ virFSPoolObjRemove(&driver->fspools, fspool);
+ def = NULL;
+ fspool = NULL;
+ goto cleanup;
+ }
+ def = NULL;
-static int
-fsPoolDestroy(virFSPoolPtr obj ATTRIBUTE_UNUSED)
-{
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("the operation is not yet supported"));
+ VIR_INFO("Defining fspool '%s'", fspool->def->name);
+ ret = virGetFSPool(conn, fspool->def->name, fspool->def->uuid,
+ NULL, NULL);
- return -1;
+ cleanup:
+
+ virStoragePoolDefFree(def);
+ if (fspool)
+ virFSPoolObjUnlock(fspool);
+ fsDriverUnlock();
+ return ret;
}
-static int
-fsPoolDelete(virFSPoolPtr obj ATTRIBUTE_UNUSED,
- unsigned int flags)
+static virFSPoolObjPtr
+virFSPoolObjFromFSPool(virFSPoolPtr fspool)
{
- virCheckFlags(0, -1);
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("the operation is not yet supported"));
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virFSPoolObjPtr ret;
- return -1;
+ fsDriverLock();
+ if (!(ret = virFSPoolObjFindByUUID(&driver->fspools, fspool->uuid))) {
+ virUUIDFormat(fspool->uuid, uuidstr);
+ virReportError(VIR_ERR_NO_FSPOOL,
+ _("no fspool with matching uuid '%s' (%s)"),
+ uuidstr, fspool->name);
+ }
+ fsDriverUnlock();
+
+ return ret;
}
static int
-fsPoolRefresh(virFSPoolPtr obj ATTRIBUTE_UNUSED,
- unsigned int flags)
+fsPoolCreate(virFSPoolPtr obj,
+ unsigned int flags)
{
- virCheckFlags(0, -1);
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("the operation is not yet supported"));
+ virFSPoolObjPtr fspool;
+ virFSBackendPtr backend;
+ int ret = -1;
+ char *stateFile = NULL;
+ unsigned int build_flags = 0;
- return -1;
-}
+ virCheckFlags(VIR_FSPOOL_CREATE_WITH_BUILD_OVERWRITE |
+ VIR_FSPOOL_CREATE_WITH_BUILD_NO_OVERWRITE, -1);
-static int
-fsPoolGetInfo(virFSPoolPtr obj ATTRIBUTE_UNUSED,
- virFSPoolInfoPtr info ATTRIBUTE_UNUSED)
-{
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("the operation is not yet supported"));
+ VIR_EXCLUSIVE_FLAGS_RET(VIR_FSPOOL_BUILD_OVERWRITE,
+ VIR_FSPOOL_BUILD_NO_OVERWRITE, -1);
- return -1;
-}
+ if (!(fspool = virFSPoolObjFromFSPool(obj)))
+ return -1;
-static char *
-fsPoolGetXMLDesc(virFSPoolPtr obj ATTRIBUTE_UNUSED,
- unsigned int flags)
-{
- virCheckFlags(0, NULL);
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("the operation is not yet supported"));
+ if (virFSPoolCreateEnsureACL(obj->conn, fspool->def) < 0)
+ goto cleanup;
- return NULL;
-}
+ if ((backend = virFSBackendForType(fspool->def->type)) == NULL)
+ goto cleanup;
-static int
-fsPoolGetAutostart(virFSPoolPtr obj ATTRIBUTE_UNUSED, int *autostart ATTRIBUTE_UNUSED)
-{
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("the operation is not yet supported"));
+ if (virFSPoolObjIsActive(fspool)) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("fspool '%s' is already active"),
+ fspool->def->name);
+ goto cleanup;
+ }
- return -1;
-}
+ if (backend->buildFSpool) {
+ if (flags & VIR_FSPOOL_CREATE_WITH_BUILD_OVERWRITE)
+ build_flags |= VIR_FSPOOL_BUILD_OVERWRITE;
+ else if (flags & VIR_FSPOOL_CREATE_WITH_BUILD_NO_OVERWRITE)
+ build_flags |= VIR_FSPOOL_BUILD_NO_OVERWRITE;
-static int
-fsPoolSetAutostart(virFSPoolPtr obj ATTRIBUTE_UNUSED, int autostart ATTRIBUTE_UNUSED)
-{
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("the operation is not yet supported"));
+ if (backend->buildFSpool(obj->conn, fspool, build_flags) < 0) {
+ virFSPoolObjRemove(&driver->fspools, fspool);
+ fspool = NULL;
+ goto cleanup;
+ }
+ }
- return -1;
-}
+ VIR_INFO("Starting up fspool '%s'", fspool->def->name);
+ if (backend->startFSpool &&
+ backend->startFSpool(obj->conn, fspool) < 0)
+ goto cleanup;
-static int
-fsPoolNumOfItems(virFSPoolPtr obj ATTRIBUTE_UNUSED)
-{
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("the operation is not yet supported"));
+ stateFile = virFileBuildPath(driver->stateDir,
+ fspool->def->name, ".xml");
- return -1;
-}
+ virFSPoolObjClearItems(fspool);
+ if (!stateFile || virFSPoolSaveState(stateFile, fspool->def) < 0 ||
+ backend->refreshFSpool(obj->conn, fspool) < 0) {
+ if (stateFile)
+ unlink(stateFile);
+ goto cleanup;
+ }
-static int
-fsPoolListItems(virFSPoolPtr obj ATTRIBUTE_UNUSED,
- char **const names ATTRIBUTE_UNUSED,
- int maxnames ATTRIBUTE_UNUSED)
-{
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("the operation is not yet supported"));
+ fspool->active = true;
+ ret = 0;
+
+ cleanup:
+ VIR_FREE(stateFile);
+ if (fspool)
+ virFSPoolObjUnlock(fspool);
+ return ret;
- return -1;
}
static int
-fsPoolListAllItems(virFSPoolPtr fspool ATTRIBUTE_UNUSED,
- virFSItemPtr **items ATTRIBUTE_UNUSED,
- unsigned int flags)
+fsPoolBuild(virFSPoolPtr obj,
+ unsigned int flags)
{
+ virFSPoolObjPtr fspool;
+ virFSBackendPtr backend;
+ int ret = -1;
+
virCheckFlags(0, -1);
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("the operation is not yet supported"));
- return -1;
-}
+ if (!(fspool = virFSPoolObjFromFSPool(obj)))
+ return -1;
-static virFSItemPtr
-fsItemLookupByName(virFSPoolPtr obj ATTRIBUTE_UNUSED, const char *name ATTRIBUTE_UNUSED)
-{
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("the operation is not yet supported"));
+ if (virFSPoolBuildEnsureACL(obj->conn, fspool->def) < 0)
+ goto cleanup;
- return NULL;
-}
+ if ((backend = virFSBackendForType(fspool->def->type)) == NULL)
+ goto cleanup;
-static virFSItemPtr
-fsItemLookupByKey(virConnectPtr conn ATTRIBUTE_UNUSED, const char *key ATTRIBUTE_UNUSED)
-{
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("the operation is not yet supported"));
+ if (virFSPoolObjIsActive(fspool)) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("fspool '%s' is already active"),
+ fspool->def->name);
+ goto cleanup;
+ }
- return NULL;
-}
+ if (backend->buildFSpool &&
+ backend->buildFSpool(obj->conn, fspool, flags) < 0)
+ goto cleanup;
-static virFSItemPtr
-fsItemLookupByPath(virConnectPtr conn ATTRIBUTE_UNUSED,
- const char *path ATTRIBUTE_UNUSED)
-{
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("the operation is not yet supported"));
+ ret = 0;
+
+ cleanup:
+ virFSPoolObjUnlock(fspool);
+ return ret;
- return NULL;
}
-static virFSItemPtr
-fsItemCreateXML(virFSPoolPtr obj ATTRIBUTE_UNUSED,
- const char *xmldesc ATTRIBUTE_UNUSED,
- unsigned int flags)
+static int
+fsPoolUndefine(virFSPoolPtr obj)
{
- virCheckFlags(0, NULL);
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("the operation is not yet supported"));
+ virFSPoolObjPtr fspool;
+ int ret = -1;
- return NULL;
-}
+ fsDriverLock();
+ if (!(fspool = virFSPoolObjFindByUUID(&driver->fspools, obj->uuid))) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(obj->uuid, uuidstr);
+ virReportError(VIR_ERR_NO_FSPOOL,
+ _("no fspool with matching uuid '%s' (%s)"),
+ uuidstr, obj->name);
+ goto cleanup;
+ }
-static virFSItemPtr
-fsItemCreateXMLFrom(virFSPoolPtr obj ATTRIBUTE_UNUSED,
- const char *xmldesc ATTRIBUTE_UNUSED,
- virFSItemPtr vobj ATTRIBUTE_UNUSED,
- unsigned int flags)
-{
- virCheckFlags(0, NULL);
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("the operation is not yet supported"));
+ if (virFSPoolUndefineEnsureACL(obj->conn, fspool->def) < 0)
+ goto cleanup;
- return NULL;
-}
+ if (virFSPoolObjIsActive(fspool)) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("fspool '%s' is still active"),
+ fspool->def->name);
+ goto cleanup;
+ }
-static int
-fsItemGetInfo(virFSItemPtr obj ATTRIBUTE_UNUSED,
- virFSItemInfoPtr info ATTRIBUTE_UNUSED)
-{
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("the operation is not yet supported"));
+ if (fspool->asyncjobs > 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("fspool '%s' has asynchronous jobs
running."),
+ fspool->def->name);
+ goto cleanup;
+ }
- return -1;
-}
+ if (virFSPoolObjDeleteDef(fspool) < 0)
+ goto cleanup;
-static char *
-fsItemGetXMLDesc(virFSItemPtr obj ATTRIBUTE_UNUSED, unsigned int flags)
-{
- virCheckFlags(0, NULL);
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("the operation is not yet supported"));
+ if (unlink(fspool->autostartLink) < 0 &&
+ errno != ENOENT &&
+ errno != ENOTDIR) {
+ char ebuf[1024];
+ VIR_ERROR(_("Failed to delete autostart link '%s': %s"),
+ fspool->autostartLink, virStrerror(errno, ebuf, sizeof(ebuf)));
+ }
- return NULL;
-}
+ VIR_FREE(fspool->configFile);
+ VIR_FREE(fspool->autostartLink);
-static char *
-fsItemGetPath(virFSItemPtr obj ATTRIBUTE_UNUSED)
-{
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("the operation is not yet supported"));
+ VIR_INFO("Undefining fspool '%s'", fspool->def->name);
+ virFSPoolObjRemove(&driver->fspools, fspool);
+ fspool = NULL;
+ ret = 0;
+
+ cleanup:
+ if (fspool)
+ virFSPoolObjUnlock(fspool);
+ fsDriverUnlock();
+ return ret;
- return NULL;
}
static int
-fsPoolIsActive(virFSPoolPtr fspool ATTRIBUTE_UNUSED)
+fsPoolDestroy(virFSPoolPtr obj)
{
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("the operation is not yet supported"));
+ virFSPoolObjPtr fspool;
+ virFSBackendPtr backend;
+ char *stateFile = NULL;
+ int ret = -1;
- return -1;
-}
+ fsDriverLock();
+ if (!(fspool = virFSPoolObjFindByUUID(&driver->fspools, obj->uuid))) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(obj->uuid, uuidstr);
+ virReportError(VIR_ERR_NO_FSPOOL,
+ _("no fspool with matching uuid '%s' (%s)"),
+ uuidstr, obj->name);
+ goto cleanup;
+ }
-static int
-fsPoolIsPersistent(virFSPoolPtr fspool ATTRIBUTE_UNUSED)
-{
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("the operation is not yet supported"));
+ if (virFSPoolDestroyEnsureACL(obj->conn, fspool->def) < 0)
+ goto cleanup;
- return -1;
+ if ((backend = virFSBackendForType(fspool->def->type)) == NULL)
+ goto cleanup;
+
+ VIR_INFO("Destroying fspool '%s'", fspool->def->name);
+
+ if (!virFSPoolObjIsActive(fspool)) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("fspool '%s' is not active"),
fspool->def->name);
+ goto cleanup;
+ }
+
+ if (fspool->asyncjobs > 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("fspool '%s' has asynchronous jobs
running."),
+ fspool->def->name);
+ goto cleanup;
+ }
+
+ if (!(stateFile = virFileBuildPath(driver->stateDir,
+ fspool->def->name,
+ ".xml")))
+ goto cleanup;
+
+ unlink(stateFile);
+ VIR_FREE(stateFile);
+
+ if (backend->stopFSpool &&
+ backend->stopFSpool(obj->conn, fspool) < 0)
+ goto cleanup;
+
+ virFSPoolObjClearItems(fspool);
+
+ fspool->active = false;
+
+ if (fspool->configFile == NULL) {
+ virFSPoolObjRemove(&driver->fspools, fspool);
+ fspool = NULL;
+ } else if (fspool->newDef) {
+ virStoragePoolDefFree(fspool->def);
+ fspool->def = fspool->newDef;
+ fspool->newDef = NULL;
+ }
+
+ ret = 0;
+
+ cleanup:
+ if (fspool)
+ virFSPoolObjUnlock(fspool);
+ fsDriverUnlock();
+ return ret;
}
static int
-fsItemDelete(virFSItemPtr obj ATTRIBUTE_UNUSED,
+fsPoolDelete(virFSPoolPtr obj,
unsigned int flags)
{
+ virFSPoolObjPtr fspool;
+ virFSBackendPtr backend;
+ char *stateFile = NULL;
+ int ret = -1;
+
virCheckFlags(0, -1);
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("the operation is not yet supported"));
- return -1;
+ if (!(fspool = virFSPoolObjFromFSPool(obj)))
+ return -1;
+
+ if (virFSPoolDeleteEnsureACL(obj->conn, fspool->def) < 0)
+ goto cleanup;
+
+ if ((backend = virFSBackendForType(fspool->def->type)) == NULL)
+ goto cleanup;
+
+ VIR_INFO("Deleting fspool '%s'", fspool->def->name);
+
+ if (virFSPoolObjIsActive(fspool)) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("fspool '%s' is still active"),
+ fspool->def->name);
+ goto cleanup;
+ }
+
+ if (fspool->asyncjobs > 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("fspool '%s' has asynchronous jobs
running."),
+ fspool->def->name);
+ goto cleanup;
+ }
+
+ if (!(stateFile = virFileBuildPath(driver->stateDir,
+ fspool->def->name,
+ ".xml")))
+ goto cleanup;
+
+ unlink(stateFile);
+ VIR_FREE(stateFile);
+
+ if (!backend->deleteFSpool) {
+ virReportError(VIR_ERR_NO_SUPPORT,
+ "%s", _("fspool does not support fspool
deletion"));
+ goto cleanup;
+ }
+ if (backend->deleteFSpool(obj->conn, fspool, flags) < 0)
+ goto cleanup;
+
+ ret = 0;
+
+ cleanup:
+ virFSPoolObjUnlock(fspool);
+ return ret;
+}
+
+static int
+fsPoolRefresh(virFSPoolPtr obj,
+ unsigned int flags)
+{
+ virFSPoolObjPtr fspool;
+ virFSBackendPtr backend;
+ int ret = -1;
+
+ virCheckFlags(0, -1);
+
+ fsDriverLock();
+ if (!(fspool = virFSPoolObjFindByUUID(&driver->fspools, obj->uuid))) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(obj->uuid, uuidstr);
+ virReportError(VIR_ERR_NO_FSPOOL,
+ _("no fspool with matching uuid '%s' (%s)"),
+ uuidstr, obj->name);
+ goto cleanup;
+ }
+
+ if (virFSPoolRefreshEnsureACL(obj->conn, fspool->def) < 0)
+ goto cleanup;
+
+ if ((backend = virFSBackendForType(fspool->def->type)) == NULL)
+ goto cleanup;
+
+ if (!virFSPoolObjIsActive(fspool)) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("fspool '%s' is not active"),
fspool->def->name);
+ goto cleanup;
+ }
+
+ if (fspool->asyncjobs > 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("fspool '%s' has asynchronous jobs
running."),
+ fspool->def->name);
+ goto cleanup;
+ }
+
+ virFSPoolObjClearItems(fspool);
+ if (backend->refreshFSpool(obj->conn, fspool) < 0) {
+ if (backend->stopFSpool)
+ backend->stopFSpool(obj->conn, fspool);
+
+ fspool->active = false;
+
+ if (fspool->configFile == NULL) {
+ virFSPoolObjRemove(&driver->fspools, fspool);
+ fspool = NULL;
+ }
+ goto cleanup;
+ }
+ ret = 0;
+
+ cleanup:
+ if (fspool)
+ virFSPoolObjUnlock(fspool);
+ fsDriverUnlock();
+ return ret;
+
+}
+
+static int
+fsPoolGetInfo(virFSPoolPtr obj,
+ virFSPoolInfoPtr info)
+{
+ virFSPoolObjPtr fspool;
+ int ret = -1;
+
+ if (!(fspool = virFSPoolObjFromFSPool(obj)))
+ return -1;
+
+ if (virFSPoolGetInfoEnsureACL(obj->conn, fspool->def) < 0)
+ goto cleanup;
+
+ if (virFSBackendForType(fspool->def->type) == NULL)
+ goto cleanup;
+
+ memset(info, 0, sizeof(virFSPoolInfo));
+ if (fspool->active)
+ info->state = VIR_FSPOOL_RUNNING;
+ else
+ info->state = VIR_FSPOOL_INACTIVE;
+ info->capacity = fspool->def->capacity;
+ info->allocation = fspool->def->allocation;
+ info->available = fspool->def->available;
+ ret = 0;
+
+ cleanup:
+ virFSPoolObjUnlock(fspool);
+ return ret;
+}
+
+static char *
+fsPoolGetXMLDesc(virFSPoolPtr obj,
+ unsigned int flags)
+{
+ virFSPoolObjPtr fspool;
+ virFSPoolDefPtr def;
+ char *ret = NULL;
+
+ virCheckFlags(VIR_FS_XML_INACTIVE, NULL);
+
+ if (!(fspool = virFSPoolObjFromFSPool(obj)))
+ return NULL;
+
+ if (virFSPoolGetXMLDescEnsureACL(obj->conn, fspool->def) < 0)
+ goto cleanup;
+
+ if ((flags & VIR_FS_XML_INACTIVE) && fspool->newDef)
+ def = fspool->newDef;
+ else
+ def = fspool->def;
+
+ ret = virFSPoolDefFormat(def);
+
+ cleanup:
+ virFSPoolObjUnlock(fspool);
+ return ret;
+}
+
+static int
+fsPoolGetAutostart(virFSPoolPtr obj, int *autostart)
+{
+ virFSPoolObjPtr fspool;
+ int ret = -1;
+
+ if (!(fspool = virFSPoolObjFromFSPool(obj)))
+ return -1;
+
+ if (virFSPoolGetAutostartEnsureACL(obj->conn, fspool->def) < 0)
+ goto cleanup;
+
+ if (!fspool->configFile) {
+ *autostart = 0;
+ } else {
+ *autostart = fspool->autostart;
+ }
+ ret = 0;
+
+ cleanup:
+ virFSPoolObjUnlock(fspool);
+ return ret;
+}
+
+static int
+fsPoolSetAutostart(virFSPoolPtr obj, int autostart)
+{
+ virFSPoolObjPtr fspool;
+ int ret = -1;
+
+ fsDriverLock();
+ fspool = virFSPoolObjFindByUUID(&driver->fspools, obj->uuid);
+
+ if (!fspool) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(obj->uuid, uuidstr);
+ virReportError(VIR_ERR_NO_FSPOOL,
+ _("no fspool with matching uuid '%s' (%s)"),
+ uuidstr, obj->name);
+ goto cleanup;
+ }
+
+ if (virFSPoolSetAutostartEnsureACL(obj->conn, fspool->def) < 0)
+ goto cleanup;
+
+ if (!fspool->configFile) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("fspool has no config file"));
+ goto cleanup;
+ }
+
+ autostart = (autostart != 0);
+
+ if (fspool->autostart != autostart) {
+ if (autostart) {
+ if (virFileMakePath(driver->autostartDir) < 0) {
+ virReportSystemError(errno,
+ _("cannot create autostart directory
%s"),
+ driver->autostartDir);
+ goto cleanup;
+ }
+
+ if (symlink(fspool->configFile, fspool->autostartLink) < 0) {
+ virReportSystemError(errno,
+ _("Failed to create symlink '%s' to
'%s'"),
+ fspool->autostartLink, fspool->configFile);
+ goto cleanup;
+ }
+ } else {
+ if (unlink(fspool->autostartLink) < 0 &&
+ errno != ENOENT && errno != ENOTDIR) {
+ virReportSystemError(errno,
+ _("Failed to delete symlink
'%s'"),
+ fspool->autostartLink);
+ goto cleanup;
+ }
+ }
+ fspool->autostart = autostart;
+ }
+ ret = 0;
+
+ cleanup:
+ if (fspool)
+ virFSPoolObjUnlock(fspool);
+ fsDriverUnlock();
+ return ret;
+}
+
+static int
+fsPoolNumOfItems(virFSPoolPtr obj)
+{
+ virFSPoolObjPtr fspool;
+ int ret = -1;
+ size_t i;
+
+ if (!(fspool = virFSPoolObjFromFSPool(obj)))
+ return -1;
+
+ if (virFSPoolNumOfItemsEnsureACL(obj->conn, fspool->def) < 0)
+ goto cleanup;
+
+ if (!virFSPoolObjIsActive(fspool)) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("fspool '%s' is not active"),
fspool->def->name);
+ goto cleanup;
+ }
+ ret = 0;
+ for (i = 0; i < fspool->items.count; i++) {
+ if (virFSPoolNumOfItemsCheckACL(obj->conn, fspool->def,
+ fspool->items.objs[i]))
+ ret++;
+ }
+
+ cleanup:
+ virFSPoolObjUnlock(fspool);
+ return ret;
+}
+
+static int
+fsPoolListItems(virFSPoolPtr obj,
+ char **const names,
+ int maxnames)
+{
+ virFSPoolObjPtr fspool;
+ size_t i;
+ int n = 0;
+
+ memset(names, 0, maxnames * sizeof(*names));
+
+ if (!(fspool = virFSPoolObjFromFSPool(obj)))
+ return -1;
+
+ if (virFSPoolListItemsEnsureACL(obj->conn, fspool->def) < 0)
+ goto cleanup;
+
+ if (!virFSPoolObjIsActive(fspool)) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("fspool '%s' is not active"),
fspool->def->name);
+ goto cleanup;
+ }
+
+ for (i = 0; i < fspool->items.count && n < maxnames; i++) {
+ if (!virFSPoolListItemsCheckACL(obj->conn, fspool->def,
+ fspool->items.objs[i]))
+ continue;
+ if (VIR_STRDUP(names[n++], fspool->items.objs[i]->name) < 0)
+ goto cleanup;
+ }
+
+ virFSPoolObjUnlock(fspool);
+ return n;
+
+ cleanup:
+ virFSPoolObjUnlock(fspool);
+ for (n = 0; n < maxnames; n++)
+ VIR_FREE(names[n]);
+
+ memset(names, 0, maxnames * sizeof(*names));
+ return -1;
+}
+
+static int
+fsPoolListAllItems(virFSPoolPtr fspool,
+ virFSItemPtr **items,
+ unsigned int flags)
+{
+ virFSPoolObjPtr obj;
+ size_t i;
+ virFSItemPtr *tmp_items = NULL;
+ virFSItemPtr item = NULL;
+ int nitems = 0;
+ int ret = -1;
+
+ virCheckFlags(0, -1);
+
+ if (!(obj = virFSPoolObjFromFSPool(fspool)))
+ return -1;
+
+ if (virFSPoolListAllItemsEnsureACL(fspool->conn, obj->def) < 0)
+ goto cleanup;
+
+ if (!virFSPoolObjIsActive(obj)) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("fspool '%s' is not active"),
obj->def->name);
+ goto cleanup;
+ }
+
+ /* Just returns the items count */
+ if (!items) {
+ ret = obj->items.count;
+ goto cleanup;
+ }
+
+ if (VIR_ALLOC_N(tmp_items, obj->items.count + 1) < 0)
+ goto cleanup;
+
+ for (i = 0; i < obj->items.count; i++) {
+ if (!virFSPoolListAllItemsCheckACL(fspool->conn, obj->def,
+ obj->items.objs[i]))
+ continue;
+ if (!(item = virGetFSItem(fspool->conn, obj->def->name,
+ obj->items.objs[i]->name,
+ obj->items.objs[i]->key,
+ NULL, NULL)))
+ goto cleanup;
+ tmp_items[nitems++] = item;
+ }
+
+ *items = tmp_items;
+ tmp_items = NULL;
+ ret = nitems;
+
+ cleanup:
+ if (tmp_items) {
+ for (i = 0; i < nitems; i++)
+ virObjectUnref(tmp_items[i]);
+ VIR_FREE(tmp_items);
+ }
+
+ virFSPoolObjUnlock(obj);
+
+ return ret;
+}
+
+static virFSItemPtr
+fsItemLookupByName(virFSPoolPtr obj, const char *name)
+{
+ virFSPoolObjPtr fspool;
+ virFSItemDefPtr item;
+ virFSItemPtr ret = NULL;
+
+ if (!(fspool = virFSPoolObjFromFSPool(obj)))
+ return NULL;
+
+ if (!virFSPoolObjIsActive(fspool)) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("fspool '%s' is not active"),
fspool->def->name);
+ goto cleanup;
+ }
+
+ item = virFSItemDefFindByName(fspool, name);
+
+ if (!item) {
+ virReportError(VIR_ERR_NO_FSITEM,
+ _("no fspool item with matching name '%s'"),
+ name);
+ goto cleanup;
+ }
+
+ if (virFSItemLookupByNameEnsureACL(obj->conn, fspool->def, item) < 0)
+ goto cleanup;
+
+ ret = virGetFSItem(obj->conn, fspool->def->name, item->name,
item->key,
+ NULL, NULL);
+
+ cleanup:
+ virFSPoolObjUnlock(fspool);
+ return ret;
+}
+
+static virFSItemPtr
+fsItemLookupByKey(virConnectPtr conn, const char *key)
+{
+ size_t i;
+ virFSItemPtr ret = NULL;
+
+ fsDriverLock();
+ for (i = 0; i < driver->fspools.count && !ret; i++) {
+ virFSPoolObjLock(driver->fspools.objs[i]);
+ if (virFSPoolObjIsActive(driver->fspools.objs[i])) {
+ virFSItemDefPtr item =
+ virFSItemDefFindByKey(driver->fspools.objs[i], key);
+
+ if (item) {
+ virFSPoolDefPtr def = driver->fspools.objs[i]->def;
+ if (virFSItemLookupByKeyEnsureACL(conn, def, item) < 0) {
+ virFSPoolObjUnlock(driver->fspools.objs[i]);
+ goto cleanup;
+ }
+
+ ret = virGetFSItem(conn,
+ def->name,
+ item->name,
+ item->key,
+ NULL, NULL);
+ }
+ }
+ virFSPoolObjUnlock(driver->fspools.objs[i]);
+ }
+
+ if (!ret)
+ virReportError(VIR_ERR_NO_FSITEM,
+ _("no fspool item with matching key %s"), key);
+
+ cleanup:
+ fsDriverUnlock();
+ return ret;
+}
+
+static virFSItemPtr
+fsItemLookupByPath(virConnectPtr conn,
+ const char *path)
+{
+ size_t i;
+ virFSItemPtr ret = NULL;
+ char *cleanpath;
+
+ cleanpath = virFileSanitizePath(path);
+ if (!cleanpath)
+ return NULL;
+
+ fsDriverLock();
+ for (i = 0; i < driver->fspools.count && !ret; i++) {
+ virFSPoolObjPtr fspool = driver->fspools.objs[i];
+ virFSItemDefPtr item;
+
+ virFSPoolObjLock(fspool);
+
+ if (!virFSPoolObjIsActive(fspool)) {
+ virFSPoolObjUnlock(fspool);
+ continue;
+ }
+
+ item = virFSItemDefFindByPath(fspool, cleanpath);
+
+ if (item) {
+ if (virFSItemLookupByPathEnsureACL(conn, fspool->def, item) < 0) {
+ virFSPoolObjUnlock(fspool);
+ goto cleanup;
+ }
+
+ ret = virGetFSItem(conn, fspool->def->name,
+ item->name, item->key,
+ NULL, NULL);
+ }
+
+ virFSPoolObjUnlock(fspool);
+ }
+
+ if (!ret) {
+ if (STREQ(path, cleanpath)) {
+ virReportError(VIR_ERR_NO_FSITEM,
+ _("no fspool item with matching path '%s'"),
path);
+ } else {
+ virReportError(VIR_ERR_NO_FSITEM,
+ _("no fspool item with matching path '%s'
(%s)"),
+ path, cleanpath);
+ }
+ }
+
+ cleanup:
+ VIR_FREE(cleanpath);
+ fsDriverUnlock();
+ return ret;
+}
+
+static void
+fsItemRemoveFromFSPool(virFSPoolObjPtr fspool,
+ virFSItemDefPtr item)
+{
+ size_t i;
+
+ for (i = 0; i < fspool->items.count; i++) {
+ if (fspool->items.objs[i] == item) {
+ VIR_INFO("Deleting item '%s' from fspool '%s'",
+ item->name, fspool->def->name);
+ virFSItemDefFree(item);
+
+ VIR_DELETE_ELEMENT(fspool->items.objs, i, fspool->items.count);
+ break;
+ }
+ }
+}
+
+static int
+fsItemDeleteInternal(virFSItemPtr obj,
+ virFSBackendPtr backend,
+ virFSPoolObjPtr fspool,
+ virFSItemDefPtr item,
+ unsigned int flags)
+{
+ int ret = -1;
+
+ virCheckFlags(0, -1);
+
+ if (!backend->deleteItem) {
+ virReportError(VIR_ERR_NO_SUPPORT,
+ "%s", _("fspool does not support item deletion"));
+ goto cleanup;
+ }
+ if (backend->deleteItem(obj->conn, fspool, item, flags) < 0)
+ goto cleanup;
+
+ fsItemRemoveFromFSPool(fspool, item);
+
+ ret = 0;
+
+ cleanup:
+ return ret;
+}
+
+static virFSItemPtr
+fsItemCreateXML(virFSPoolPtr obj,
+ const char *xmldesc,
+ unsigned int flags)
+{
+
+ virFSPoolObjPtr fspool;
+ virFSBackendPtr backend;
+ virFSItemDefPtr itemdef = NULL;
+ virFSItemPtr ret = NULL, itemobj = NULL;
+
+ virCheckFlags(0, NULL);
+
+ if (!(fspool = virFSPoolObjFromFSPool(obj)))
+ return NULL;
+
+ if (!virFSPoolObjIsActive(fspool)) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("fspool '%s' is not active"),
fspool->def->name);
+ goto cleanup;
+ }
+
+ if ((backend = virFSBackendForType(fspool->def->type)) == NULL)
+ goto cleanup;
+
+ itemdef = virFSItemDefParseString(fspool->def, xmldesc,
+ VIR_ITEM_XML_PARSE_OPT_CAPACITY);
+ if (itemdef == NULL)
+ goto cleanup;
+
+ if (!itemdef->target.capacity && !backend->buildItem) {
+ virReportError(VIR_ERR_NO_SUPPORT,
+ "%s", _("item capacity required for this "
+ "fspool"));
+ goto cleanup;
+ }
+
+ if (virFSItemCreateXMLEnsureACL(obj->conn, fspool->def, itemdef) < 0)
+ goto cleanup;
+
+ if (virFSItemDefFindByName(fspool, itemdef->name)) {
+ virReportError(VIR_ERR_FSITEM_EXIST,
+ _("'%s'"), itemdef->name);
+ goto cleanup;
+ }
+
+ if (!backend->createItem) {
+ virReportError(VIR_ERR_NO_SUPPORT,
+ "%s", _("fspool does not support item "
+ "creation"));
+ goto cleanup;
+ }
+
+ if (VIR_REALLOC_N(fspool->items.objs,
+ fspool->items.count+1) < 0)
+ goto cleanup;
+
+ /* Wipe any key the user may have suggested, as item creation
+ * will generate the canonical key. */
+ VIR_FREE(itemdef->key);
+ if (backend->createItem(obj->conn, fspool, itemdef) < 0)
+ goto cleanup;
+
+ fspool->items.objs[fspool->items.count++] = itemdef;
+ itemobj = virGetFSItem(obj->conn, fspool->def->name, itemdef->name,
+ itemdef->key, NULL, NULL);
+ if (!itemobj) {
+ fspool->items.count--;
+ goto cleanup;
+ }
+
+
+ if (backend->buildItem) {
+ int buildret;
+ virFSItemDefPtr builditemdef = NULL;
+
+ if (VIR_ALLOC(builditemdef) < 0) {
+ itemdef = NULL;
+ goto cleanup;
+ }
+
+ /* Make a shallow copy of the 'defined' item definition, since the
+ * original allocation value will change as the user polls 'info',
+ * but we only need the initial requested values
+ */
+ memcpy(builditemdef, itemdef, sizeof(*itemdef));
+
+ /* Drop the fspool lock during item allocation */
+ fspool->asyncjobs++;
+ itemdef->building = true;
+ virFSPoolObjUnlock(fspool);
+
+ buildret = backend->buildItem(obj->conn, fspool, builditemdef, flags);
+
+ VIR_FREE(builditemdef);
+
+ fsDriverLock();
+ virFSPoolObjLock(fspool);
+ fsDriverUnlock();
+
+ itemdef->building = false;
+ fspool->asyncjobs--;
+
+ if (buildret < 0) {
+ /* buildItem handles deleting item on failure */
+ fsItemRemoveFromFSPool(fspool, itemdef);
+ itemdef = NULL;
+ goto cleanup;
+ }
+
+ }
+
+ if (backend->refreshItem &&
+ backend->refreshItem(obj->conn, fspool, itemdef) < 0) {
+ fsItemDeleteInternal(itemobj, backend, fspool, itemdef, 0);
+ itemdef = NULL;
+ goto cleanup;
+ }
+
+ /* Update fspool metadata ignoring the disk backend since
+ * it updates the fspool values.
+ */
+
+ VIR_INFO("Creating item '%s' in fspool '%s'",
+ itemobj->name, fspool->def->name);
+ ret = itemobj;
+ itemobj = NULL;
+ itemdef = NULL;
+
+ cleanup:
+ virObjectUnref(itemobj);
+ virFSItemDefFree(itemdef);
+ if (fspool)
+ virFSPoolObjUnlock(fspool);
+ return ret;
+}
+
+static virFSItemPtr
+fsItemCreateXMLFrom(virFSPoolPtr obj,
+ const char *xmldesc,
+ virFSItemPtr vobj,
+ unsigned int flags)
+{
+ virFSPoolObjPtr fspool, origpool = NULL;
+ virFSBackendPtr backend;
+ virFSItemDefPtr origitem = NULL, newitem = NULL, shadowitem = NULL;
+ virFSItemPtr ret = NULL, itemobj = NULL;
+ int buildret;
+
+ virCheckFlags(0, NULL);
+
+ fsDriverLock();
+ fspool = virFSPoolObjFindByUUID(&driver->fspools, obj->uuid);
+ if (fspool && STRNEQ(obj->name, vobj->pool)) {
+ virFSPoolObjUnlock(fspool);
+ origpool = virFSPoolObjFindByName(&driver->fspools, vobj->pool);
+ virFSPoolObjLock(fspool);
+ }
+ fsDriverUnlock();
+ if (!fspool) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(obj->uuid, uuidstr);
+ virReportError(VIR_ERR_NO_FSPOOL,
+ _("no fspool with matching uuid '%s' (%s)"),
+ uuidstr, obj->name);
+ goto cleanup;
+ }
+
+ if (STRNEQ(obj->name, vobj->pool) && !origpool) {
+ virReportError(VIR_ERR_NO_FSPOOL,
+ _("no fspool with matching name '%s'"),
+ vobj->pool);
+ goto cleanup;
+ }
+
+ if (!virFSPoolObjIsActive(fspool)) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("fspool '%s' is not active"),
fspool->def->name);
+ goto cleanup;
+ }
+
+ if (origpool && !virFSPoolObjIsActive(origpool)) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("fspool '%s' is not active"),
+ origpool->def->name);
+ goto cleanup;
+ }
+
+ if ((backend = virFSBackendForType(fspool->def->type)) == NULL)
+ goto cleanup;
+
+ origitem = virFSItemDefFindByName(origpool ?
+ origpool : fspool, vobj->name);
+ if (!origitem) {
+ virReportError(VIR_ERR_NO_FSITEM,
+ _("no fsitem with matching name '%s'"),
+ vobj->name);
+ goto cleanup;
+ }
+
+ newitem = virFSItemDefParseString(fspool->def, xmldesc,
+ VIR_VOL_XML_PARSE_NO_CAPACITY);
+ if (newitem == NULL)
+ goto cleanup;
+
+ if (virFSItemCreateXMLFromEnsureACL(obj->conn, fspool->def, newitem) < 0)
+ goto cleanup;
+
+ if (virFSItemDefFindByName(fspool, newitem->name)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("fsitem name '%s' already in use."),
+ newitem->name);
+ goto cleanup;
+ }
+
+ /* Use the original item's capacity in case the new capacity
+ * is less than that, or it was omitted */
+ if (newitem->target.capacity < origitem->target.capacity)
+ newitem->target.capacity = origitem->target.capacity;
+
+ if (!backend->buildItemFrom) {
+ virReportError(VIR_ERR_NO_SUPPORT,
+ "%s", _("fspool does not support"
+ " item creation from an existing item"));
+ goto cleanup;
+ }
+
+ if (origitem->building) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("fsitem '%s' is still being allocated."),
+ origitem->name);
+ goto cleanup;
+ }
+
+ if (backend->refreshItem &&
+ backend->refreshItem(obj->conn, fspool, origitem) < 0)
+ goto cleanup;
+
+ if (VIR_REALLOC_N(fspool->items.objs,
+ fspool->items.count+1) < 0)
+ goto cleanup;
+
+ /* 'Define' the new item so we get async progress reporting.
+ * Wipe any key the user may have suggested, as item creation
+ * will generate the canonical key. */
+ VIR_FREE(newitem->key);
+ if (backend->createItem(obj->conn, fspool, newitem) < 0)
+ goto cleanup;
+
+ /* Make a shallow copy of the 'defined' item definition, since the
+ * original allocation value will change as the user polls 'info',
+ * but we only need the initial requested values
+ */
+ if (VIR_ALLOC(shadowitem) < 0)
+ goto cleanup;
+
+ memcpy(shadowitem, newitem, sizeof(*newitem));
+
+ fspool->items.objs[fspool->items.count++] = newitem;
+ itemobj = virGetFSItem(obj->conn, fspool->def->name, newitem->name,
+ newitem->key, NULL, NULL);
+ if (!itemobj) {
+ fspool->items.count--;
+ goto cleanup;
+ }
+
+ /* Drop the fspool lock during item allocation */
+ fspool->asyncjobs++;
+ newitem->building = true;
+ origitem->in_use++;
+ virFSPoolObjUnlock(fspool);
+
+ if (origpool) {
+ origpool->asyncjobs++;
+ virFSPoolObjUnlock(origpool);
+ }
+
+ buildret = backend->buildItemFrom(obj->conn, fspool, shadowitem, origitem,
flags);
+
+ fsDriverLock();
+ virFSPoolObjLock(fspool);
+ if (origpool)
+ virFSPoolObjLock(origpool);
+ fsDriverUnlock();
+
+ origitem->in_use--;
+ newitem->building = false;
+ fspool->asyncjobs--;
+
+ if (origpool) {
+ origpool->asyncjobs--;
+ virFSPoolObjUnlock(origpool);
+ origpool = NULL;
+ }
+
+ if (buildret < 0 ||
+ (backend->refreshItem &&
+ backend->refreshItem(obj->conn, fspool, newitem) < 0)) {
+ fsItemDeleteInternal(itemobj, backend, fspool, newitem, 0);
+ newitem = NULL;
+ goto cleanup;
+ }
+
+ fspool->def->allocation += newitem->target.allocation;
+ fspool->def->available -= newitem->target.allocation;
+
+ VIR_INFO("Creating item '%s' in fspool '%s'",
+ itemobj->name, fspool->def->name);
+ ret = itemobj;
+ itemobj = NULL;
+ newitem = NULL;
+
+ cleanup:
+ virObjectUnref(itemobj);
+ virFSItemDefFree(newitem);
+ VIR_FREE(shadowitem);
+ if (fspool)
+ virFSPoolObjUnlock(fspool);
+ if (origpool)
+ virFSPoolObjUnlock(origpool);
+ return ret;
+}
+
+static virFSItemDefPtr
+virFSItemDefFromItem(virFSItemPtr obj,
+ virFSPoolObjPtr *fspool,
+ virFSBackendPtr *backend)
+{
+ virFSItemDefPtr item = NULL;
+
+ *fspool = NULL;
+
+ fsDriverLock();
+ *fspool = virFSPoolObjFindByName(&driver->fspools, obj->pool);
+ fsDriverUnlock();
+
+ if (!*fspool) {
+ virReportError(VIR_ERR_NO_FSPOOL,
+ _("no fspool with matching name '%s'"),
+ obj->pool);
+ return NULL;
+ }
+
+ if (!virFSPoolObjIsActive(*fspool)) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("fspool '%s' is not active"),
+ (*fspool)->def->name);
+ goto error;
+ }
+
+ if (!(item = virFSItemDefFindByName(*fspool, obj->name))) {
+ virReportError(VIR_ERR_NO_FSITEM,
+ _("no fsitem with matching name '%s'"),
+ obj->name);
+ goto error;
+ }
+
+ if (backend) {
+ if (!(*backend = virFSBackendForType((*fspool)->def->type)))
+ goto error;
+ }
+
+ return item;
+
+ error:
+ virFSPoolObjUnlock(*fspool);
+ *fspool = NULL;
+
+ return NULL;
+}
+
+static int
+fsItemGetInfo(virFSItemPtr obj,
+ virFSItemInfoPtr info)
+{
+ virFSPoolObjPtr fspool;
+ virFSBackendPtr backend;
+ virFSItemDefPtr item;
+ int ret = -1;
+
+ if (!(item = virFSItemDefFromItem(obj, &fspool, &backend)))
+ return -1;
+
+ if (virFSItemGetInfoEnsureACL(obj->conn, fspool->def, item) < 0)
+ goto cleanup;
+
+ if (backend->refreshItem &&
+ backend->refreshItem(obj->conn, fspool, item) < 0)
+ goto cleanup;
+
+ memset(info, 0, sizeof(*info));
+ info->type = item->type;
+ info->capacity = item->target.capacity;
+ info->allocation = item->target.allocation;
+ ret = 0;
+
+ cleanup:
+ virFSPoolObjUnlock(fspool);
+ return ret;
+}
+
+static char *
+fsItemGetXMLDesc(virFSItemPtr obj, unsigned int flags)
+{
+ virFSPoolObjPtr fspool;
+ virFSBackendPtr backend;
+ virFSItemDefPtr item;
+ char *ret = NULL;
+
+ virCheckFlags(0, NULL);
+
+ if (!(item = virFSItemDefFromItem(obj, &fspool, &backend)))
+ return NULL;
+
+ if (virFSItemGetXMLDescEnsureACL(obj->conn, fspool->def, item) < 0)
+ goto cleanup;
+
+ if (backend->refreshItem &&
+ backend->refreshItem(obj->conn, fspool, item) < 0)
+ goto cleanup;
+
+ ret = virFSItemDefFormat(fspool->def, item);
+
+ cleanup:
+ virFSPoolObjUnlock(fspool);
+
+ return ret;
+}
+
+static char *
+fsItemGetPath(virFSItemPtr obj)
+{
+ virFSPoolObjPtr fspool;
+ virFSItemDefPtr item;
+ char *ret = NULL;
+
+ if (!(item = virFSItemDefFromItem(obj, &fspool, NULL)))
+ return NULL;
+
+ if (virFSItemGetPathEnsureACL(obj->conn, fspool->def, item) < 0)
+ goto cleanup;
+
+ ignore_value(VIR_STRDUP(ret, item->target.path));
+
+ cleanup:
+ virFSPoolObjUnlock(fspool);
+ return ret;
+}
+
+static int
+fsPoolIsActive(virFSPoolPtr fspool)
+{
+ virFSPoolObjPtr obj;
+ int ret = -1;
+
+ if (!(obj = virFSPoolObjFromFSPool(fspool)))
+ return -1;
+
+ if (virFSPoolIsActiveEnsureACL(fspool->conn, obj->def) < 0)
+ goto cleanup;
+
+ ret = virFSPoolObjIsActive(obj);
+
+ cleanup:
+ virFSPoolObjUnlock(obj);
+ return ret;
+}
+
+static int
+fsPoolIsPersistent(virFSPoolPtr fspool)
+{
+ virFSPoolObjPtr obj;
+ int ret = -1;
+
+ if (!(obj = virFSPoolObjFromFSPool(fspool)))
+ return -1;
+
+ if (virFSPoolIsPersistentEnsureACL(fspool->conn, obj->def) < 0)
+ goto cleanup;
+
+ ret = obj->configFile ? 1 : 0;
+
+ cleanup:
+ virFSPoolObjUnlock(obj);
+ return ret;
+}
+
+static int
+fsItemDelete(virFSItemPtr obj,
+ unsigned int flags)
+{
+ virFSPoolObjPtr fspool;
+ virFSBackendPtr backend;
+ virFSItemDefPtr item = NULL;
+ int ret = -1;
+
+ virCheckFlags(0, -1);
+
+ if (!(item = virFSItemDefFromItem(obj, &fspool, &backend)))
+ return -1;
+
+ if (virFSItemDeleteEnsureACL(obj->conn, fspool->def, item) < 0)
+ goto cleanup;
+
+ if (item->in_use) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("item '%s' is still in use."),
+ item->name);
+ goto cleanup;
+ }
+
+ if (item->building) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("item '%s' is still being allocated."),
+ item->name);
+ goto cleanup;
+ }
+
+ if (fsItemDeleteInternal(obj, backend, fspool, item, flags) < 0)
+ goto cleanup;
+
+ ret = 0;
+
+ cleanup:
+ virFSPoolObjUnlock(fspool);
+ return ret;
}
static virFSDriver fsDriver = {
--
1.8.3.1