Signed-off-by: Olga Krishtal <okrishtal@xxxxxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list