storage: remember relative names in backing chain

In order to search for a backing file name as literally present
in a chain, we need to remember if the chain had relative names.
Also, searching for absolute names is easier if we only have
to canonicalize once, rather than on every iteration.

* src/util/storage_file.h (_virStorageFileMetadata): Add field.
* src/util/storage_file.c (virStorageFileGetMetadataFromBuf):
(virStorageFileFreeMetadata): Manage it
(absolutePathFromBaseFile): Store absolute names in canonical form.
This commit is contained in:
Eric Blake 2012-10-09 17:47:42 -06:00
parent 1fc9593271
commit 82507838e0
2 changed files with 23 additions and 10 deletions

View File

@ -28,6 +28,7 @@
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#ifdef __linux__
# if HAVE_LINUX_MAGIC_H
# include <linux/magic.h>
@ -530,18 +531,22 @@ static char *
absolutePathFromBaseFile(const char *base_file, const char *path)
{
char *res;
char *tmp;
size_t d_len = dir_len (base_file);
/* If path is already absolute, or if dirname(base_file) is ".",
just return a copy of path. */
if (*path == '/' || d_len == 0)
return strdup(path);
return canonicalize_file_name(path);
/* Ensure that the following cast-to-int is valid. */
if (d_len > INT_MAX)
return NULL;
ignore_value(virAsprintf(&res, "%.*s/%s", (int) d_len, base_file, path));
if (virAsprintf(&tmp, "%.*s/%s", (int) d_len, base_file, path) < 0)
return NULL;
res = canonicalize_file_name(tmp);
VIR_FREE(tmp);
return res;
}
@ -697,17 +702,23 @@ virStorageFileGetMetadataFromBuf(int format,
meta->backingStoreIsFile = false;
if (backing != NULL) {
if (virBackingStoreIsFile(backing)) {
meta->backingStoreIsFile = true;
meta->backingStore = absolutePathFromBaseFile(path, backing);
} else {
meta->backingStore = strdup(backing);
}
VIR_FREE(backing);
meta->backingStore = strdup(backing);
if (meta->backingStore == NULL) {
virReportOOMError();
VIR_FREE(backing);
return -1;
}
if (virBackingStoreIsFile(backing)) {
meta->backingStoreIsFile = true;
meta->backingStoreRaw = meta->backingStore;
meta->backingStore = absolutePathFromBaseFile(path, backing);
if (meta->backingStore == NULL) {
virReportOOMError();
VIR_FREE(backing);
return -1;
}
}
VIR_FREE(backing);
meta->backingStoreFormat = backingFormat;
} else {
meta->backingStore = NULL;
@ -1014,6 +1025,7 @@ virStorageFileFreeMetadata(virStorageFileMetadata *meta)
virStorageFileFreeMetadata(meta->backingMeta);
VIR_FREE(meta->backingStore);
VIR_FREE(meta->backingStoreRaw);
VIR_FREE(meta);
}

View File

@ -53,7 +53,8 @@ VIR_ENUM_DECL(virStorageFileFormat);
typedef struct _virStorageFileMetadata virStorageFileMetadata;
typedef virStorageFileMetadata *virStorageFileMetadataPtr;
struct _virStorageFileMetadata {
char *backingStore;
char *backingStore; /* Canonical name (absolute file, or protocol) */
char *backingStoreRaw; /* If file, original name, possibly relative */
int backingStoreFormat; /* enum virStorageFileFormat */
bool backingStoreIsFile;
virStorageFileMetadataPtr backingMeta;