storage: backend: Add unique id retrieval API

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.
This commit is contained in:
Peter Krempa 2014-04-22 16:02:54 +02:00
parent b20060bae2
commit 684ec651e9
4 changed files with 83 additions and 0 deletions

View File

@ -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 */

View File

@ -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 */

View File

@ -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);
}

View File

@ -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);