Move some pool functions to storage_util to create local/common helpers
using the same naming syntax as the existing upload, download, and wipe
virStorageBackend*Local API's.
In the process of doing so, found a few API's that can now become local
to storage_util. In order to distinguish between local/external - I
changed the names of the now local only ones from "virStorageBackend..."
to just "storageBackend..."
Signed-off-by: John Ferlan <jferlan@xxxxxxxxxx>
---
src/storage/storage_backend_fs.c | 383 ++---------------------------------
src/storage/storage_util.c | 420 ++++++++++++++++++++++++++++++++++++---
src/storage/storage_util.h | 37 ++--
3 files changed, 432 insertions(+), 408 deletions(-)
diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c
index 67e36be..6f331d6 100644
--- a/src/storage/storage_backend_fs.c
+++ b/src/storage/storage_backend_fs.c
@@ -23,11 +23,9 @@
#include <config.h>
-#include <sys/statvfs.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
-#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
@@ -53,126 +51,6 @@
VIR_LOG_INIT("storage.storage_backend_fs");
-#define VIR_STORAGE_VOL_FS_OPEN_FLAGS (VIR_STORAGE_VOL_OPEN_DEFAULT | \
- VIR_STORAGE_VOL_OPEN_DIR)
-#define VIR_STORAGE_VOL_FS_PROBE_FLAGS (VIR_STORAGE_VOL_FS_OPEN_FLAGS | \
- VIR_STORAGE_VOL_OPEN_NOERROR)
-
-static int
-virStorageBackendProbeTarget(virStorageSourcePtr target,
- virStorageEncryptionPtr *encryption)
-{
- int backingStoreFormat;
- int fd = -1;
- int ret = -1;
- int rc;
- virStorageSourcePtr meta = NULL;
- struct stat sb;
-
- if (encryption)
- *encryption = NULL;
-
- if ((rc = virStorageBackendVolOpen(target->path, &sb,
- VIR_STORAGE_VOL_FS_PROBE_FLAGS)) < 0)
- return rc; /* Take care to propagate rc, it is not always -1 */
- fd = rc;
-
- if (virStorageBackendUpdateVolTargetInfoFD(target, fd, &sb) < 0)
- goto cleanup;
-
- if (S_ISDIR(sb.st_mode)) {
- if (virStorageBackendIsPloopDir(target->path)) {
- if (virStorageBackendRedoPloopUpdate(target, &sb, &fd,
- VIR_STORAGE_VOL_FS_PROBE_FLAGS) < 0)
- goto cleanup;
- } else {
- target->format = VIR_STORAGE_FILE_DIR;
- ret = 0;
- goto cleanup;
- }
- }
-
- if (!(meta = virStorageFileGetMetadataFromFD(target->path,
- fd,
- VIR_STORAGE_FILE_AUTO,
- &backingStoreFormat)))
- goto cleanup;
-
- if (meta->backingStoreRaw) {
- if (!(target->backingStore = virStorageSourceNewFromBacking(meta)))
- goto cleanup;
-
- target->backingStore->format = backingStoreFormat;
-
- /* XXX: Remote storage doesn't play nicely with volumes backed by
- * remote storage. To avoid trouble, just fake the backing store is RAW
- * and put the string from the metadata as the path of the target. */
- if (!virStorageSourceIsLocalStorage(target->backingStore)) {
- virStorageSourceFree(target->backingStore);
-
- if (VIR_ALLOC(target->backingStore) < 0)
- goto cleanup;
-
- target->backingStore->type = VIR_STORAGE_TYPE_NETWORK;
- target->backingStore->path = meta->backingStoreRaw;
- meta->backingStoreRaw = NULL;
- target->backingStore->format = VIR_STORAGE_FILE_RAW;
- }
-
- if (target->backingStore->format == VIR_STORAGE_FILE_AUTO) {
- if ((rc = virStorageFileProbeFormat(target->backingStore->path,
- -1, -1)) < 0) {
- /* If the backing file is currently unavailable or is
- * accessed via remote protocol only log an error, fake the
- * format as RAW and continue. Returning -1 here would
- * disable the whole storage pool, making it unavailable for
- * even maintenance. */
- target->backingStore->format = VIR_STORAGE_FILE_RAW;
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("cannot probe backing volume format: %s"),
- target->backingStore->path);
- } else {
- target->backingStore->format = rc;
- }
- }
- }
-
- target->format = meta->format;
-
- /* Default to success below this point */
- ret = 0;
-
- if (meta->capacity)
- target->capacity = meta->capacity;
-
- if (encryption && meta->encryption) {
- *encryption = meta->encryption;
- meta->encryption = NULL;
-
- /* XXX ideally we'd fill in secret UUID here
- * but we cannot guarantee 'conn' is non-NULL
- * at this point in time :-( So we only fill
- * in secrets when someone first queries a vol
- */
- }
-
- virBitmapFree(target->features);
- target->features = meta->features;
- meta->features = NULL;
-
- if (meta->compat) {
- VIR_FREE(target->compat);
- target->compat = meta->compat;
- meta->compat = NULL;
- }
-
- cleanup:
- VIR_FORCE_CLOSE(fd);
- virStorageSourceFree(meta);
- return ret;
-
-}
-
#if WITH_STORAGE_FS
# include <mntent.h>
@@ -574,8 +452,6 @@ static int
virStorageBackendFileSystemStop(virConnectPtr conn ATTRIBUTE_UNUSED,
virStoragePoolObjPtr pool)
{
- virCommandPtr cmd = NULL;
- int ret = -1;
int rc;
if (virStorageBackendFileSystemIsValid(pool) < 0)
@@ -585,17 +461,7 @@ virStorageBackendFileSystemStop(virConnectPtr conn ATTRIBUTE_UNUSED,
if ((rc = virStorageBackendFileSystemIsMounted(pool)) != 1)
return rc;
- cmd = virCommandNewArgList(UMOUNT,
- pool->def->target.path,
- NULL);
-
- if (virCommandRun(cmd, NULL) < 0)
- goto cleanup;
-
- ret = 0;
- cleanup:
- virCommandFree(cmd);
- return ret;
+ return virStorageBackendUmountLocal(pool);
}
#endif /* WITH_STORAGE_FS */
@@ -742,237 +608,18 @@ virStorageBackendFileSystemBuild(virConnectPtr conn ATTRIBUTE_UNUSED,
virStoragePoolObjPtr pool,
unsigned int flags)
{
- int ret = -1;
- char *parent = NULL;
- char *p = NULL;
- mode_t mode;
- bool needs_create_as_uid;
- unsigned int dir_create_flags;
-
virCheckFlags(VIR_STORAGE_POOL_BUILD_OVERWRITE |
- VIR_STORAGE_POOL_BUILD_NO_OVERWRITE, ret);
+ VIR_STORAGE_POOL_BUILD_NO_OVERWRITE, -1);
- VIR_EXCLUSIVE_FLAGS_GOTO(VIR_STORAGE_POOL_BUILD_OVERWRITE,
- VIR_STORAGE_POOL_BUILD_NO_OVERWRITE,
- error);
+ VIR_EXCLUSIVE_FLAGS_RET(VIR_STORAGE_POOL_BUILD_OVERWRITE,
+ VIR_STORAGE_POOL_BUILD_NO_OVERWRITE,
+ -1);
- if (VIR_STRDUP(parent, pool->def->target.path) < 0)
- goto error;
- if (!(p = strrchr(parent, '/'))) {
- virReportError(VIR_ERR_INVALID_ARG,
- _("path '%s' is not absolute"),
- pool->def->target.path);
- goto error;
- }
-
- if (p != parent) {
- /* assure all directories in the path prior to the final dir
- * exist, with default uid/gid/mode. */
- *p = '\0';
- if (virFileMakePath(parent) < 0) {
- virReportSystemError(errno, _("cannot create path '%s'"),
- parent);
- goto error;
- }
- }
-
- dir_create_flags = VIR_DIR_CREATE_ALLOW_EXIST;
- needs_create_as_uid = (pool->def->type == VIR_STORAGE_POOL_NETFS);
- mode = pool->def->target.perms.mode;
-
- if (mode == (mode_t) -1 &&
- (needs_create_as_uid || !virFileExists(pool->def->target.path)))
- mode = VIR_STORAGE_DEFAULT_POOL_PERM_MODE;
- if (needs_create_as_uid)
- dir_create_flags |= VIR_DIR_CREATE_AS_UID;
-
- /* Now create the final dir in the path with the uid/gid/mode
- * requested in the config. If the dir already exists, just set
- * the perms. */
- if (virDirCreate(pool->def->target.path,
- mode,
- pool->def->target.perms.uid,
- pool->def->target.perms.gid,
- dir_create_flags) < 0)
- goto error;
-
- if (flags != 0) {
- ret = virStorageBackendMakeFileSystem(pool, flags);
- } else {
- ret = 0;
- }
-
- error:
- VIR_FREE(parent);
- return ret;
-}
-
-
-/**
- * Iterate over the pool's directory and enumerate all disk images
- * within it. This is non-recursive.
- */
-static int
-virStorageBackendFileSystemRefresh(virConnectPtr conn ATTRIBUTE_UNUSED,
- virStoragePoolObjPtr pool)
-{
- DIR *dir;
- struct dirent *ent;
- struct statvfs sb;
- struct stat statbuf;
- virStorageVolDefPtr vol = NULL;
- virStorageSourcePtr target = NULL;
- int direrr;
- int fd = -1, ret = -1;
-
- if (virDirOpen(&dir, pool->def->target.path) < 0)
- goto cleanup;
-
- while ((direrr = virDirRead(dir, &ent, pool->def->target.path)) > 0) {
- int err;
-
- if (virStringHasControlChars(ent->d_name)) {
- VIR_WARN("Ignoring file with control characters under '%s'",
- pool->def->target.path);
- continue;
- }
-
- if (VIR_ALLOC(vol) < 0)
- goto cleanup;
-
- if (VIR_STRDUP(vol->name, ent->d_name) < 0)
- goto cleanup;
-
- vol->type = VIR_STORAGE_VOL_FILE;
- vol->target.format = VIR_STORAGE_FILE_RAW; /* Real value is filled in during probe */
- if (virAsprintf(&vol->target.path, "%s/%s",
- pool->def->target.path,
- vol->name) == -1)
- goto cleanup;
-
- if (VIR_STRDUP(vol->key, vol->target.path) < 0)
- goto cleanup;
-
- if ((err = virStorageBackendProbeTarget(&vol->target,
- &vol->target.encryption)) < 0) {
- if (err == -2) {
- /* Silently ignore non-regular files,
- * eg 'lost+found', dangling symbolic link */
- virStorageVolDefFree(vol);
- vol = NULL;
- continue;
- } else if (err == -3) {
- /* The backing file is currently unavailable, its format is not
- * explicitly specified, the probe to auto detect the format
- * failed: continue with faked RAW format, since AUTO will
- * break virStorageVolTargetDefFormat() generating the line
- * <format type='...'/>. */
- } else {
- goto cleanup;
- }
- }
-
- /* directory based volume */
- if (vol->target.format == VIR_STORAGE_FILE_DIR)
- vol->type = VIR_STORAGE_VOL_DIR;
-
- if (vol->target.format == VIR_STORAGE_FILE_PLOOP)
- vol->type = VIR_STORAGE_VOL_PLOOP;
-
- if (vol->target.backingStore) {
- ignore_value(virStorageBackendUpdateVolTargetInfo(VIR_STORAGE_VOL_FILE,
- vol->target.backingStore,
- false,
- VIR_STORAGE_VOL_OPEN_DEFAULT, 0));
- /* If this failed, the backing file is currently unavailable,
- * the capacity, allocation, owner, group and mode are unknown.
- * An error message was raised, but we just continue. */
- }
-
- if (VIR_APPEND_ELEMENT(pool->volumes.objs, pool->volumes.count, vol) < 0)
- goto cleanup;
- }
- if (direrr < 0)
- goto cleanup;
- VIR_DIR_CLOSE(dir);
- vol = NULL;
-
- if (VIR_ALLOC(target))
- goto cleanup;
-
- if ((fd = open(pool->def->target.path, O_RDONLY)) < 0) {
- virReportSystemError(errno,
- _("cannot open path '%s'"),
- pool->def->target.path);
- goto cleanup;
- }
-
- if (fstat(fd, &statbuf) < 0) {
- virReportSystemError(errno,
- _("cannot stat path '%s'"),
- pool->def->target.path);
- goto cleanup;
- }
-
- if (virStorageBackendUpdateVolTargetInfoFD(target, fd, &statbuf) < 0)
- goto cleanup;
-
- /* VolTargetInfoFD doesn't update capacity correctly for the pool case */
- if (statvfs(pool->def->target.path, &sb) < 0) {
- virReportSystemError(errno,
- _("cannot statvfs path '%s'"),
- pool->def->target.path);
- goto cleanup;
- }
-
- pool->def->capacity = ((unsigned long long)sb.f_frsize *
- (unsigned long long)sb.f_blocks);
- pool->def->available = ((unsigned long long)sb.f_bfree *
- (unsigned long long)sb.f_frsize);
- pool->def->allocation = pool->def->capacity - pool->def->available;
-
- pool->def->target.perms.mode = target->perms->mode;
- pool->def->target.perms.uid = target->perms->uid;
- pool->def->target.perms.gid = target->perms->gid;
- VIR_FREE(pool->def->target.perms.label);
- if (VIR_STRDUP(pool->def->target.perms.label, target->perms->label) < 0)
- goto cleanup;
-
- ret = 0;
- cleanup:
- VIR_DIR_CLOSE(dir);
- VIR_FORCE_CLOSE(fd);
- virStorageVolDefFree(vol);
- virStorageSourceFree(target);
- if (ret < 0)
- virStoragePoolObjClearVols(pool);
- return ret;
-}
-
-
-/**
- * @conn connection to report errors against
- * @pool storage pool to delete
- *
- * Delete a directory based storage pool
- *
- * Returns 0 on success, -1 on error
- */
-static int
-virStorageBackendFileSystemDelete(virConnectPtr conn ATTRIBUTE_UNUSED,
- virStoragePoolObjPtr pool,
- unsigned int flags)
-{
- virCheckFlags(0, -1);
-
- /* XXX delete all vols first ? */
-
- if (rmdir(pool->def->target.path) < 0) {
- virReportSystemError(errno,
- _("failed to remove pool '%s'"),
- pool->def->target.path);
+ if (virStorageBackendBuildLocal(pool) < 0)
return -1;
- }
+
+ if (flags != 0)
+ return virStorageBackendMakeFileSystem(pool, flags);
return 0;
}
@@ -1319,8 +966,8 @@ virStorageBackend virStorageBackendDirectory = {
.buildPool = virStorageBackendFileSystemBuild,
.checkPool = virStorageBackendFileSystemCheck,
- .refreshPool = virStorageBackendFileSystemRefresh,
- .deletePool = virStorageBackendFileSystemDelete,
+ .refreshPool = virStorageBackendRefreshLocal,
+ .deletePool = virStorageBackendDeleteLocal,
.buildVol = virStorageBackendFileSystemVolBuild,
.buildVolFrom = virStorageBackendFileSystemVolBuildFrom,
.createVol = virStorageBackendFileSystemVolCreate,
@@ -1339,9 +986,9 @@ virStorageBackend virStorageBackendFileSystem = {
.buildPool = virStorageBackendFileSystemBuild,
.checkPool = virStorageBackendFileSystemCheck,
.startPool = virStorageBackendFileSystemStart,
- .refreshPool = virStorageBackendFileSystemRefresh,
+ .refreshPool = virStorageBackendRefreshLocal,
.stopPool = virStorageBackendFileSystemStop,
- .deletePool = virStorageBackendFileSystemDelete,
+ .deletePool = virStorageBackendDeleteLocal,
.buildVol = virStorageBackendFileSystemVolBuild,
.buildVolFrom = virStorageBackendFileSystemVolBuildFrom,
.createVol = virStorageBackendFileSystemVolCreate,
@@ -1359,9 +1006,9 @@ virStorageBackend virStorageBackendNetFileSystem = {
.checkPool = virStorageBackendFileSystemCheck,
.startPool = virStorageBackendFileSystemStart,
.findPoolSources = virStorageBackendFileSystemNetFindPoolSources,
- .refreshPool = virStorageBackendFileSystemRefresh,
+ .refreshPool = virStorageBackendRefreshLocal,
.stopPool = virStorageBackendFileSystemStop,
- .deletePool = virStorageBackendFileSystemDelete,
+ .deletePool = virStorageBackendDeleteLocal,
.buildVol = virStorageBackendFileSystemVolBuild,
.buildVolFrom = virStorageBackendFileSystemVolBuildFrom,
.createVol = virStorageBackendFileSystemVolCreate,
diff --git a/src/storage/storage_util.c b/src/storage/storage_util.c
index e16c1a4..6c2678d 100644
--- a/src/storage/storage_util.c
+++ b/src/storage/storage_util.c
@@ -26,6 +26,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
+#include <sys/statvfs.h>
#include <sys/param.h>
#include <dirent.h>
#include "dirname.h"
@@ -1675,8 +1676,8 @@ virStorageBackendVolOpen(const char *path, struct stat *sb,
/* virStorageIsPloop function checks whether given directory is ploop volume's
* directory.
*/
-bool
-virStorageBackendIsPloopDir(char *path)
+static bool
+storageBackendIsPloopDir(char *path)
{
bool ret = false;
char *root = NULL;
@@ -1702,9 +1703,9 @@ virStorageBackendIsPloopDir(char *path)
* and etc. we need to perform virStorageBackendVolOpen and
* virStorageBackendUpdateVolTargetFd once again.
*/
-int
-virStorageBackendRedoPloopUpdate(virStorageSourcePtr target, struct stat *sb,
- int *fd, unsigned int flags)
+static int
+storageBackendRedoPloopUpdate(virStorageSourcePtr target, struct stat *sb,
+ int *fd, unsigned int flags)
{
char *path = NULL;
int ret = -1;
@@ -1723,7 +1724,7 @@ virStorageBackendRedoPloopUpdate(virStorageSourcePtr target, struct stat *sb,
}
/*
- * virStorageBackendUpdateVolTargetInfo
+ * storageBackendUpdateVolTargetInfo
* @voltype: Volume type
* @target: target definition ptr of volume to update
* @withBlockVolFormat: true if caller determined a block file
@@ -1736,12 +1737,12 @@ virStorageBackendRedoPloopUpdate(virStorageSourcePtr target, struct stat *sb,
* open error occurred. It is up to the caller to handle. A -2 may also
* be returned if the caller passed a readflagsflag.
*/
-int
-virStorageBackendUpdateVolTargetInfo(virStorageVolType voltype,
- virStorageSourcePtr target,
- bool withBlockVolFormat,
- unsigned int openflags,
- unsigned int readflags)
+static int
+storageBackendUpdateVolTargetInfo(virStorageVolType voltype,
+ virStorageSourcePtr target,
+ bool withBlockVolFormat,
+ unsigned int openflags,
+ unsigned int readflags)
{
int ret, fd = -1;
struct stat sb;
@@ -1758,9 +1759,9 @@ virStorageBackendUpdateVolTargetInfo(virStorageVolType voltype,
if ((voltype == VIR_STORAGE_VOL_FILE || voltype == VIR_STORAGE_VOL_BLOCK) &&
target->format != VIR_STORAGE_FILE_NONE) {
if (S_ISDIR(sb.st_mode)) {
- if (virStorageBackendIsPloopDir(target->path)) {
- if ((ret = virStorageBackendRedoPloopUpdate(target, &sb, &fd,
- openflags)) < 0)
+ if (storageBackendIsPloopDir(target->path)) {
+ if ((ret = storageBackendRedoPloopUpdate(target, &sb, &fd,
+ openflags)) < 0)
goto cleanup;
target->format = VIR_STORAGE_FILE_PLOOP;
} else {
@@ -1826,19 +1827,19 @@ virStorageBackendUpdateVolInfo(virStorageVolDefPtr vol,
{
int ret;
- if ((ret = virStorageBackendUpdateVolTargetInfo(vol->type,
- &vol->target,
- withBlockVolFormat,
- openflags, readflags)) < 0)
+ if ((ret = storageBackendUpdateVolTargetInfo(vol->type,
+ &vol->target,
+ withBlockVolFormat,
+ openflags, readflags)) < 0)
return ret;
if (vol->target.backingStore &&
- (ret = virStorageBackendUpdateVolTargetInfo(VIR_STORAGE_VOL_FILE,
- vol->target.backingStore,
- withBlockVolFormat,
- VIR_STORAGE_VOL_OPEN_DEFAULT |
- VIR_STORAGE_VOL_OPEN_NOERROR,
- readflags) < 0))
+ (ret = storageBackendUpdateVolTargetInfo(VIR_STORAGE_VOL_FILE,
+ vol->target.backingStore,
+ withBlockVolFormat,
+ VIR_STORAGE_VOL_OPEN_DEFAULT |
+ VIR_STORAGE_VOL_OPEN_NOERROR,
+ readflags) < 0))
return ret;
return 0;
@@ -2408,6 +2409,118 @@ virStorageBackendVolWipeLocal(virConnectPtr conn ATTRIBUTE_UNUSED,
/**
+ * @pool: storage pool to build
+ * @dir_create_flags: flags for directory creation
+ *
+ * Common code to build a directory based storage pool
+ *
+ * Returns 0 on success, -1 on failure
+ */
+int
+virStorageBackendBuildLocal(virStoragePoolObjPtr pool)
+{
+ int ret = -1;
+ char *parent = NULL;
+ char *p = NULL;
+ mode_t mode;
+ bool needs_create_as_uid;
+ unsigned int dir_create_flags;
+
+ if (VIR_STRDUP(parent, pool->def->target.path) < 0)
+ goto cleanup;
+ if (!(p = strrchr(parent, '/'))) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("path '%s' is not absolute"),
+ pool->def->target.path);
+ goto cleanup;
+ }
+
+ if (p != parent) {
+ /* assure all directories in the path prior to the final dir
+ * exist, with default uid/gid/mode. */
+ *p = '\0';
+ if (virFileMakePath(parent) < 0) {
+ virReportSystemError(errno, _("cannot create path '%s'"),
+ parent);
+ goto cleanup;
+ }
+ }
+
+ dir_create_flags = VIR_DIR_CREATE_ALLOW_EXIST;
+ needs_create_as_uid = (pool->def->type == VIR_STORAGE_POOL_NETFS);
+ mode = pool->def->target.perms.mode;
+
+ if (mode == (mode_t) -1 &&
+ (needs_create_as_uid || !virFileExists(pool->def->target.path)))
+ mode = VIR_STORAGE_DEFAULT_POOL_PERM_MODE;
+ if (needs_create_as_uid)
+ dir_create_flags |= VIR_DIR_CREATE_AS_UID;
+
+ /* Now create the final dir in the path with the uid/gid/mode
+ * requested in the config. If the dir already exists, just set
+ * the perms. */
+ if (virDirCreate(pool->def->target.path,
+ mode,
+ pool->def->target.perms.uid,
+ pool->def->target.perms.gid,
+ dir_create_flags) < 0)
+ goto cleanup;
+
+ ret = 0;
+
+ cleanup:
+ VIR_FREE(parent);
+ return ret;
+}
+
+
+int
+virStorageBackendUmountLocal(virStoragePoolObjPtr pool)
+{
+ int ret = -1;
+ virCommandPtr cmd = virCommandNewArgList(UMOUNT, pool->def->target.path,
+ NULL);
+
+ if (virCommandRun(cmd, NULL) < 0)
+ goto cleanup;
+
+ ret = 0;
+
+ cleanup:
+ virCommandFree(cmd);
+ return ret;
+}
+
+
+/**
+ * @conn connection to report errors against
+ * @pool storage pool to delete
+ *
+ * Delete a directory based storage pool
+ *
+ * Returns 0 on success, -1 on error
+ */
+int
+virStorageBackendDeleteLocal(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virStoragePoolObjPtr pool,
+ unsigned int flags)
+{
+ virCheckFlags(0, -1);
+
+ /* XXX delete all vols first ? */
+
+ if (rmdir(pool->def->target.path) < 0) {
+ virReportSystemError(errno,
+ _("failed to remove pool '%s'"),
+ pool->def->target.path);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/**
* virStorageBackendFindGlusterPoolSources:
* @host: host to detect volumes on
* @pooltype: src->format is set to this value
@@ -2919,6 +3032,263 @@ virStorageBackendDeviceIsEmpty(const char *devpath,
}
+static int
+storageBackendProbeTarget(virStorageSourcePtr target,
+ virStorageEncryptionPtr *encryption)
+{
+ int backingStoreFormat;
+ int fd = -1;
+ int ret = -1;
+ int rc;
+ virStorageSourcePtr meta = NULL;
+ struct stat sb;
+
+ if (encryption)
+ *encryption = NULL;
+
+ if ((rc = virStorageBackendVolOpen(target->path, &sb,
+ VIR_STORAGE_VOL_FS_PROBE_FLAGS)) < 0)
+ return rc; /* Take care to propagate rc, it is not always -1 */
+ fd = rc;
+
+ if (virStorageBackendUpdateVolTargetInfoFD(target, fd, &sb) < 0)
+ goto cleanup;
+
+ if (S_ISDIR(sb.st_mode)) {
+ if (storageBackendIsPloopDir(target->path)) {
+ if (storageBackendRedoPloopUpdate(target, &sb, &fd,
+ VIR_STORAGE_VOL_FS_PROBE_FLAGS) < 0)
+ goto cleanup;
+ } else {
+ target->format = VIR_STORAGE_FILE_DIR;
+ ret = 0;
+ goto cleanup;
+ }
+ }
+
+ if (!(meta = virStorageFileGetMetadataFromFD(target->path,
+ fd,
+ VIR_STORAGE_FILE_AUTO,
+ &backingStoreFormat)))
+ goto cleanup;
+
+ if (meta->backingStoreRaw) {
+ if (!(target->backingStore = virStorageSourceNewFromBacking(meta)))
+ goto cleanup;
+
+ target->backingStore->format = backingStoreFormat;
+
+ /* XXX: Remote storage doesn't play nicely with volumes backed by
+ * remote storage. To avoid trouble, just fake the backing store is RAW
+ * and put the string from the metadata as the path of the target. */
+ if (!virStorageSourceIsLocalStorage(target->backingStore)) {
+ virStorageSourceFree(target->backingStore);
+
+ if (VIR_ALLOC(target->backingStore) < 0)
+ goto cleanup;
+
+ target->backingStore->type = VIR_STORAGE_TYPE_NETWORK;
+ target->backingStore->path = meta->backingStoreRaw;
+ meta->backingStoreRaw = NULL;
+ target->backingStore->format = VIR_STORAGE_FILE_RAW;
+ }
+
+ if (target->backingStore->format == VIR_STORAGE_FILE_AUTO) {
+ if ((rc = virStorageFileProbeFormat(target->backingStore->path,
+ -1, -1)) < 0) {
+ /* If the backing file is currently unavailable or is
+ * accessed via remote protocol only log an error, fake the
+ * format as RAW and continue. Returning -1 here would
+ * disable the whole storage pool, making it unavailable for
+ * even maintenance. */
+ target->backingStore->format = VIR_STORAGE_FILE_RAW;
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot probe backing volume format: %s"),
+ target->backingStore->path);
+ } else {
+ target->backingStore->format = rc;
+ }
+ }
+ }
+
+ target->format = meta->format;
+
+ /* Default to success below this point */
+ ret = 0;
+
+ if (meta->capacity)
+ target->capacity = meta->capacity;
+
+ if (encryption && meta->encryption) {
+ *encryption = meta->encryption;
+ meta->encryption = NULL;
+
+ /* XXX ideally we'd fill in secret UUID here
+ * but we cannot guarantee 'conn' is non-NULL
+ * at this point in time :-( So we only fill
+ * in secrets when someone first queries a vol
+ */
+ }
+
+ virBitmapFree(target->features);
+ target->features = meta->features;
+ meta->features = NULL;
+
+ if (meta->compat) {
+ VIR_FREE(target->compat);
+ target->compat = meta->compat;
+ meta->compat = NULL;
+ }
+
+ cleanup:
+ VIR_FORCE_CLOSE(fd);
+ virStorageSourceFree(meta);
+ return ret;
+}
+
+
+/**
+ * Iterate over the pool's directory and enumerate all disk images
+ * within it. This is non-recursive.
+ */
+int
+virStorageBackendRefreshLocal(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virStoragePoolObjPtr pool)
+{
+ DIR *dir;
+ struct dirent *ent;
+ struct statvfs sb;
+ struct stat statbuf;
+ virStorageVolDefPtr vol = NULL;
+ virStorageSourcePtr target = NULL;
+ int direrr;
+ int fd = -1, ret = -1;
+
+ if (virDirOpen(&dir, pool->def->target.path) < 0)
+ goto cleanup;
+
+ while ((direrr = virDirRead(dir, &ent, pool->def->target.path)) > 0) {
+ int err;
+
+ if (virStringHasControlChars(ent->d_name)) {
+ VIR_WARN("Ignoring file with control characters under '%s'",
+ pool->def->target.path);
+ continue;
+ }
+
+ if (VIR_ALLOC(vol) < 0)
+ goto cleanup;
+
+ if (VIR_STRDUP(vol->name, ent->d_name) < 0)
+ goto cleanup;
+
+ vol->type = VIR_STORAGE_VOL_FILE;
+ vol->target.format = VIR_STORAGE_FILE_RAW; /* Real value is filled in during probe */
+ if (virAsprintf(&vol->target.path, "%s/%s",
+ pool->def->target.path,
+ vol->name) == -1)
+ goto cleanup;
+
+ if (VIR_STRDUP(vol->key, vol->target.path) < 0)
+ goto cleanup;
+
+ if ((err = storageBackendProbeTarget(&vol->target,
+ &vol->target.encryption)) < 0) {
+ if (err == -2) {
+ /* Silently ignore non-regular files,
+ * eg 'lost+found', dangling symbolic link */
+ virStorageVolDefFree(vol);
+ vol = NULL;
+ continue;
+ } else if (err == -3) {
+ /* The backing file is currently unavailable, its format is not
+ * explicitly specified, the probe to auto detect the format
+ * failed: continue with faked RAW format, since AUTO will
+ * break virStorageVolTargetDefFormat() generating the line
+ * <format type='...'/>. */
+ } else {
+ goto cleanup;
+ }
+ }
+
+ /* directory based volume */
+ if (vol->target.format == VIR_STORAGE_FILE_DIR)
+ vol->type = VIR_STORAGE_VOL_DIR;
+
+ if (vol->target.format == VIR_STORAGE_FILE_PLOOP)
+ vol->type = VIR_STORAGE_VOL_PLOOP;
+
+ if (vol->target.backingStore) {
+ ignore_value(storageBackendUpdateVolTargetInfo(VIR_STORAGE_VOL_FILE,
+ vol->target.backingStore,
+ false,
+ VIR_STORAGE_VOL_OPEN_DEFAULT, 0));
+ /* If this failed, the backing file is currently unavailable,
+ * the capacity, allocation, owner, group and mode are unknown.
+ * An error message was raised, but we just continue. */
+ }
+
+ if (VIR_APPEND_ELEMENT(pool->volumes.objs, pool->volumes.count, vol) < 0)
+ goto cleanup;
+ }
+ if (direrr < 0)
+ goto cleanup;
+ VIR_DIR_CLOSE(dir);
+ vol = NULL;
+
+ if (VIR_ALLOC(target))
+ goto cleanup;
+
+ if ((fd = open(pool->def->target.path, O_RDONLY)) < 0) {
+ virReportSystemError(errno,
+ _("cannot open path '%s'"),
+ pool->def->target.path);
+ goto cleanup;
+ }
+
+ if (fstat(fd, &statbuf) < 0) {
+ virReportSystemError(errno,
+ _("cannot stat path '%s'"),
+ pool->def->target.path);
+ goto cleanup;
+ }
+
+ if (virStorageBackendUpdateVolTargetInfoFD(target, fd, &statbuf) < 0)
+ goto cleanup;
+
+ /* VolTargetInfoFD doesn't update capacity correctly for the pool case */
+ if (statvfs(pool->def->target.path, &sb) < 0) {
+ virReportSystemError(errno,
+ _("cannot statvfs path '%s'"),
+ pool->def->target.path);
+ goto cleanup;
+ }
+
+ pool->def->capacity = ((unsigned long long)sb.f_frsize *
+ (unsigned long long)sb.f_blocks);
+ pool->def->available = ((unsigned long long)sb.f_bfree *
+ (unsigned long long)sb.f_frsize);
+ pool->def->allocation = pool->def->capacity - pool->def->available;
+
+ pool->def->target.perms.mode = target->perms->mode;
+ pool->def->target.perms.uid = target->perms->uid;
+ pool->def->target.perms.gid = target->perms->gid;
+ VIR_FREE(pool->def->target.perms.label);
+ if (VIR_STRDUP(pool->def->target.perms.label, target->perms->label) < 0)
+ goto cleanup;
+
+ ret = 0;
+ cleanup:
+ VIR_DIR_CLOSE(dir);
+ VIR_FORCE_CLOSE(fd);
+ virStorageVolDefFree(vol);
+ virStorageSourceFree(target);
+ if (ret < 0)
+ virStoragePoolObjClearVols(pool);
+ return ret;
+}
+
+
static char *
virStorageBackendSCSISerial(const char *dev)
{
diff --git a/src/storage/storage_util.h b/src/storage/storage_util.h
index e127381..f5a1b5b 100644
--- a/src/storage/storage_util.h
+++ b/src/storage/storage_util.h
@@ -49,20 +49,10 @@ int virStorageBackendCreatePloop(virConnectPtr conn,
int virStoragePloopResize(virStorageVolDefPtr vol,
unsigned long long capacity);
-int virStorageBackendRedoPloopUpdate(virStorageSourcePtr target,
- struct stat *sb, int *fd,
- unsigned int flags);
-bool virStorageBackendIsPloopDir(char *path);
-
virStorageBackendBuildVolFrom
virStorageBackendGetBuildVolFromFunction(virStorageVolDefPtr vol,
virStorageVolDefPtr inputvol);
-int virStorageBackendFindGlusterPoolSources(const char *host,
- int pooltype,
- virStoragePoolSourceListPtr list,
- bool report);
-
int virStorageBackendVolUploadLocal(virConnectPtr conn,
virStoragePoolObjPtr pool,
virStorageVolDefPtr vol,
@@ -84,6 +74,23 @@ int virStorageBackendVolWipeLocal(virConnectPtr conn,
unsigned int algorithm,
unsigned int flags);
+/* Local/Common Storage Pool Backend APIs */
+int virStorageBackendBuildLocal(virStoragePoolObjPtr pool);
+
+int virStorageBackendUmountLocal(virStoragePoolObjPtr pool);
+
+int virStorageBackendDeleteLocal(virConnectPtr conn,
+ virStoragePoolObjPtr pool,
+ unsigned int flags);
+
+int virStorageBackendRefreshLocal(virConnectPtr conn,
+ virStoragePoolObjPtr pool);
+
+int virStorageBackendFindGlusterPoolSources(const char *host,
+ int pooltype,
+ virStoragePoolSourceListPtr list,
+ bool report);
+
bool virStorageBackendDeviceIsEmpty(const char *devpath,
const char *format,
bool writelabel);
@@ -110,6 +117,11 @@ enum {
# define VIR_STORAGE_VOL_OPEN_DEFAULT (VIR_STORAGE_VOL_OPEN_REG |\
VIR_STORAGE_VOL_OPEN_BLOCK)
+# define VIR_STORAGE_VOL_FS_OPEN_FLAGS (VIR_STORAGE_VOL_OPEN_DEFAULT | \
+ VIR_STORAGE_VOL_OPEN_DIR)
+# define VIR_STORAGE_VOL_FS_PROBE_FLAGS (VIR_STORAGE_VOL_FS_OPEN_FLAGS | \
+ VIR_STORAGE_VOL_OPEN_NOERROR)
+
int virStorageBackendVolOpen(const char *path, struct stat *sb,
unsigned int flags)
ATTRIBUTE_RETURN_CHECK
@@ -122,11 +134,6 @@ int virStorageBackendUpdateVolInfo(virStorageVolDefPtr vol,
bool withBlockVolFormat,
unsigned int openflags,
unsigned int readflags);
-int virStorageBackendUpdateVolTargetInfo(virStorageVolType voltype,
- virStorageSourcePtr target,
- bool withBlockVolFormat,
- unsigned int openflags,
- unsigned int readflags);
int virStorageBackendUpdateVolTargetInfoFD(virStorageSourcePtr target,
int fd,
struct stat *sb);