Different protocols have different means to uniquely identify a storage
file. This patch implements a storage driver API to retrieve a unique
string describing a volume. The current implementation works for local
storage only and returns the canonical path of the volume.
To add caching support the local filesystem driver now has a private
structure holding the cached string, which is created only when it's
initially accessed.
This patch provides the implementation for local files only for start.
---
Notes:
Version 3:
- changed name of variable from uid to canonpath
- documented validity scope of the returned name
src/storage/storage_backend.h | 3 +++
src/storage/storage_backend_fs.c | 49 ++++++++++++++++++++++++++++++++++++++++
src/storage/storage_driver.c | 30 ++++++++++++++++++++++++
src/storage/storage_driver.h | 1 +
4 files changed, 83 insertions(+)
diff --git a/src/storage/storage_backend.h b/src/storage/storage_backend.h
index 6be5ca7..5d71cde 100644
--- a/src/storage/storage_backend.h
+++ b/src/storage/storage_backend.h
@@ -195,6 +195,8 @@ typedef ssize_t
ssize_t max_len,
char **buf);
+typedef const char *
+(*virStorageFileBackendGetUniqueIdentifier)(virStorageSourcePtr src);
virStorageFileBackendPtr virStorageFileBackendForType(int type, int protocol);
@@ -211,6 +213,7 @@ struct _virStorageFileBackend {
virStorageFileBackendInit backendInit;
virStorageFileBackendDeinit backendDeinit;
virStorageFileBackendReadHeader storageFileReadHeader;
+ virStorageFileBackendGetUniqueIdentifier storageFileGetUniqueIdentifier;
/* The following group of callbacks is expected to set errno
* and return -1 on error. No libvirt error shall be reported */
diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c
index 003c6df..aed07a6 100644
--- a/src/storage/storage_backend_fs.c
+++ b/src/storage/storage_backend_fs.c
@@ -1333,6 +1333,14 @@ virStorageBackend virStorageBackendNetFileSystem = {
};
+typedef struct _virStorageFileBackendFsPriv virStorageFileBackendFsPriv;
+typedef virStorageFileBackendFsPriv *virStorageFileBackendFsPrivPtr;
+
+struct _virStorageFileBackendFsPriv {
+ char *canonpath; /* unique file identifier (canonical path) */
+};
+
+
static void
virStorageFileBackendFileDeinit(virStorageSourcePtr src)
{
@@ -1340,16 +1348,27 @@ virStorageFileBackendFileDeinit(virStorageSourcePtr src)
virStorageTypeToString(virStorageSourceGetActualType(src)),
src->path);
+ virStorageFileBackendFsPrivPtr priv = src->drv->priv;
+
+ VIR_FREE(priv->canonpath);
+ VIR_FREE(priv);
}
static int
virStorageFileBackendFileInit(virStorageSourcePtr src)
{
+ virStorageFileBackendFsPrivPtr priv = NULL;
+
VIR_DEBUG("initializing FS storage file %p (%s:%s)", src,
virStorageTypeToString(virStorageSourceGetActualType(src)),
src->path);
+ if (VIR_ALLOC(priv) < 0)
+ return -1;
+
+ src->drv->priv = priv;
+
return 0;
}
@@ -1397,6 +1416,23 @@ virStorageFileBackendFileReadHeader(virStorageSourcePtr src,
}
+static const char *
+virStorageFileBackendFileGetUniqueIdentifier(virStorageSourcePtr src)
+{
+ virStorageFileBackendFsPrivPtr priv = src->drv->priv;
+
+ if (!priv->canonpath) {
+ if (!(priv->canonpath = canonicalize_file_name(src->path))) {
+ virReportSystemError(errno, _("can't canonicalize path
'%s'"),
+ src->path);
+ return NULL;
+ }
+ }
+
+ return priv->canonpath;
+}
+
+
virStorageFileBackend virStorageFileBackendFile = {
.type = VIR_STORAGE_TYPE_FILE,
@@ -1406,6 +1442,8 @@ virStorageFileBackend virStorageFileBackendFile = {
.storageFileUnlink = virStorageFileBackendFileUnlink,
.storageFileStat = virStorageFileBackendFileStat,
.storageFileReadHeader = virStorageFileBackendFileReadHeader,
+
+ .storageFileGetUniqueIdentifier = virStorageFileBackendFileGetUniqueIdentifier,
};
@@ -1417,7 +1455,18 @@ virStorageFileBackend virStorageFileBackendBlock = {
.storageFileStat = virStorageFileBackendFileStat,
.storageFileReadHeader = virStorageFileBackendFileReadHeader,
+
+ .storageFileGetUniqueIdentifier = virStorageFileBackendFileGetUniqueIdentifier,
};
+virStorageFileBackend virStorageFileBackendDir = {
+ .type = VIR_STORAGE_TYPE_DIR,
+
+ .backendInit = virStorageFileBackendFileInit,
+ .backendDeinit = virStorageFileBackendFileDeinit,
+
+ .storageFileGetUniqueIdentifier = virStorageFileBackendFileGetUniqueIdentifier,
+};
+
#endif /* WITH_STORAGE_FS */
diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
index cd6babe..0c779c5 100644
--- a/src/storage/storage_driver.c
+++ b/src/storage/storage_driver.c
@@ -2987,3 +2987,33 @@ virStorageFileReadHeader(virStorageSourcePtr src,
return ret;
}
+
+
+/*
+ * virStorageFileGetUniqueIdentifier: Get a unique string describing the volume
+ *
+ * @src: file structure pointing to the file
+ *
+ * Returns a string uniquely describing a single volume (canonical path).
+ * The string shall not be freed and is valid until the storage file is
+ * deinitialized. Returns NULL on error and sets a libvirt error code */
+const char *
+virStorageFileGetUniqueIdentifier(virStorageSourcePtr src)
+{
+ if (!virStorageFileIsInitialized(src)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("storage file backend not initialized"));
+ return NULL;
+ }
+
+ if (!src->drv->backend->storageFileGetUniqueIdentifier) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unique storage file identifier not implemented for "
+ "storage type %s (protocol: %s)'"),
+ virStorageTypeToString(src->type),
+ virStorageNetProtocolTypeToString(src->protocol));
+ return NULL;
+ }
+
+ return src->drv->backend->storageFileGetUniqueIdentifier(src);
+}
diff --git a/src/storage/storage_driver.h b/src/storage/storage_driver.h
index d67d74b..9280ef0 100644
--- a/src/storage/storage_driver.h
+++ b/src/storage/storage_driver.h
@@ -41,6 +41,7 @@ int virStorageFileStat(virStorageSourcePtr src,
ssize_t virStorageFileReadHeader(virStorageSourcePtr src,
ssize_t max_len,
char **buf);
+const char *virStorageFileGetUniqueIdentifier(virStorageSourcePtr src);
int storageRegister(void);
--
1.9.3