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. --- 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 33551e7..1f436fa 100644 --- a/src/storage/storage_backend_fs.c +++ b/src/storage/storage_backend_fs.c @@ -1339,6 +1339,14 @@ virStorageBackend virStorageBackendNetFileSystem = { }; +typedef struct _virStorageFileBackendFsPriv virStorageFileBackendFsPriv; +typedef virStorageFileBackendFsPriv *virStorageFileBackendFsPrivPtr; + +struct _virStorageFileBackendFsPriv { + char *uid; /* unique file identifier (canonical path) */ +}; + + static void virStorageFileBackendFileDeinit(virStorageSourcePtr src) { @@ -1346,16 +1354,27 @@ virStorageFileBackendFileDeinit(virStorageSourcePtr src) virStorageTypeToString(virStorageSourceGetActualType(src)), src->path); + virStorageFileBackendFsPrivPtr priv = src->drv->priv; + + VIR_FREE(priv->uid); + 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; } @@ -1403,6 +1422,23 @@ virStorageFileBackendFileReadHeader(virStorageSourcePtr src, } +static const char * +virStorageFileBackendFileGetUniqueIdentifier(virStorageSourcePtr src) +{ + virStorageFileBackendFsPrivPtr priv = src->drv->priv; + + if (!priv->uid) { + if (!(priv->uid = canonicalize_file_name(src->path))) { + virReportSystemError(errno, _("can't canonicalize path '%s'"), + src->path); + return NULL; + } + } + + return priv->uid; +} + + virStorageFileBackend virStorageFileBackendFile = { .type = VIR_STORAGE_TYPE_FILE, @@ -1412,6 +1448,8 @@ virStorageFileBackend virStorageFileBackendFile = { .storageFileUnlink = virStorageFileBackendFileUnlink, .storageFileStat = virStorageFileBackendFileStat, .storageFileReadHeader = virStorageFileBackendFileReadHeader, + + .storageFileGetUniqueIdentifier = virStorageFileBackendFileGetUniqueIdentifier, }; @@ -1423,7 +1461,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 3019531..2036bfd 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. 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list