mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 17:34:18 +03:00
storage: Avoid memory leak on metadata fetching
Getting metadata on storage allocates a memory (path) which need to be freed after use otherwise it gets leaked. This means after use of virStorageFileGetMetadataFromFD or virStorageFileGetMetadata one must call virStorageFileFreeMetadata to free it. This function frees structure internals and structure itself.
This commit is contained in:
parent
c3fd09f7b7
commit
85aa40e26d
1
cfg.mk
1
cfg.mk
@ -156,6 +156,7 @@ useless_free_options = \
|
|||||||
--name=virSecretDefFree \
|
--name=virSecretDefFree \
|
||||||
--name=virStorageEncryptionFree \
|
--name=virStorageEncryptionFree \
|
||||||
--name=virStorageEncryptionSecretFree \
|
--name=virStorageEncryptionSecretFree \
|
||||||
|
--name=virStorageFileFreeMetadata \
|
||||||
--name=virStoragePoolDefFree \
|
--name=virStoragePoolDefFree \
|
||||||
--name=virStoragePoolObjFree \
|
--name=virStoragePoolObjFree \
|
||||||
--name=virStoragePoolSourceFree \
|
--name=virStoragePoolSourceFree \
|
||||||
|
@ -11049,10 +11049,16 @@ int virDomainDiskDefForeachPath(virDomainDiskDefPtr disk,
|
|||||||
int ret = -1;
|
int ret = -1;
|
||||||
size_t depth = 0;
|
size_t depth = 0;
|
||||||
char *nextpath = NULL;
|
char *nextpath = NULL;
|
||||||
|
virStorageFileMetadata *meta;
|
||||||
|
|
||||||
if (!disk->src || disk->type == VIR_DOMAIN_DISK_TYPE_NETWORK)
|
if (!disk->src || disk->type == VIR_DOMAIN_DISK_TYPE_NETWORK)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (VIR_ALLOC(meta) < 0) {
|
||||||
|
virReportOOMError();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
if (disk->driverType) {
|
if (disk->driverType) {
|
||||||
const char *formatStr = disk->driverType;
|
const char *formatStr = disk->driverType;
|
||||||
if (STREQ(formatStr, "aio"))
|
if (STREQ(formatStr, "aio"))
|
||||||
@ -11078,7 +11084,6 @@ int virDomainDiskDefForeachPath(virDomainDiskDefPtr disk,
|
|||||||
paths = virHashCreate(5, NULL);
|
paths = virHashCreate(5, NULL);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
virStorageFileMetadata meta;
|
|
||||||
const char *path = nextpath ? nextpath : disk->src;
|
const char *path = nextpath ? nextpath : disk->src;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
@ -11106,7 +11111,7 @@ int virDomainDiskDefForeachPath(virDomainDiskDefPtr disk,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (virStorageFileGetMetadataFromFD(path, fd, format, &meta) < 0) {
|
if (virStorageFileGetMetadataFromFD(path, fd, format, meta) < 0) {
|
||||||
VIR_FORCE_CLOSE(fd);
|
VIR_FORCE_CLOSE(fd);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@ -11120,16 +11125,18 @@ int virDomainDiskDefForeachPath(virDomainDiskDefPtr disk,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
depth++;
|
depth++;
|
||||||
nextpath = meta.backingStore;
|
VIR_FREE(nextpath);
|
||||||
|
nextpath = meta->backingStore;
|
||||||
|
meta->backingStore = NULL;
|
||||||
|
|
||||||
/* Stop iterating if we reach a non-file backing store */
|
/* Stop iterating if we reach a non-file backing store */
|
||||||
if (nextpath && !meta.backingStoreIsFile) {
|
if (nextpath && !meta->backingStoreIsFile) {
|
||||||
VIR_DEBUG("Stopping iteration on non-file backing store: %s",
|
VIR_DEBUG("Stopping iteration on non-file backing store: %s",
|
||||||
nextpath);
|
nextpath);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
format = meta.backingStoreFormat;
|
format = meta->backingStoreFormat;
|
||||||
|
|
||||||
if (format == VIR_STORAGE_FILE_AUTO &&
|
if (format == VIR_STORAGE_FILE_AUTO &&
|
||||||
!allowProbing)
|
!allowProbing)
|
||||||
@ -11145,6 +11152,7 @@ int virDomainDiskDefForeachPath(virDomainDiskDefPtr disk,
|
|||||||
cleanup:
|
cleanup:
|
||||||
virHashFree(paths);
|
virHashFree(paths);
|
||||||
VIR_FREE(nextpath);
|
VIR_FREE(nextpath);
|
||||||
|
virStorageFileFreeMetadata(meta);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -940,6 +940,7 @@ virStorageGenerateQcowPassphrase;
|
|||||||
# storage_file.h
|
# storage_file.h
|
||||||
virStorageFileFormatTypeFromString;
|
virStorageFileFormatTypeFromString;
|
||||||
virStorageFileFormatTypeToString;
|
virStorageFileFormatTypeToString;
|
||||||
|
virStorageFileFreeMetadata;
|
||||||
virStorageFileGetMetadata;
|
virStorageFileGetMetadata;
|
||||||
virStorageFileGetMetadataFromFD;
|
virStorageFileGetMetadataFromFD;
|
||||||
virStorageFileIsSharedFS;
|
virStorageFileIsSharedFS;
|
||||||
|
@ -61,8 +61,14 @@ virStorageBackendProbeTarget(virStorageVolTargetPtr target,
|
|||||||
unsigned long long *capacity,
|
unsigned long long *capacity,
|
||||||
virStorageEncryptionPtr *encryption)
|
virStorageEncryptionPtr *encryption)
|
||||||
{
|
{
|
||||||
int fd, ret;
|
int fd = -1;
|
||||||
virStorageFileMetadata meta;
|
int ret = -1;
|
||||||
|
virStorageFileMetadata *meta;
|
||||||
|
|
||||||
|
if (VIR_ALLOC(meta) < 0) {
|
||||||
|
virReportOOMError();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
*backingStore = NULL;
|
*backingStore = NULL;
|
||||||
*backingStoreFormat = VIR_STORAGE_FILE_AUTO;
|
*backingStoreFormat = VIR_STORAGE_FILE_AUTO;
|
||||||
@ -71,36 +77,33 @@ virStorageBackendProbeTarget(virStorageVolTargetPtr target,
|
|||||||
|
|
||||||
if ((ret = virStorageBackendVolOpenCheckMode(target->path,
|
if ((ret = virStorageBackendVolOpenCheckMode(target->path,
|
||||||
VIR_STORAGE_VOL_FS_REFRESH_FLAGS)) < 0)
|
VIR_STORAGE_VOL_FS_REFRESH_FLAGS)) < 0)
|
||||||
return ret; /* Take care to propagate ret, it is not always -1 */
|
goto error; /* Take care to propagate ret, it is not always -1 */
|
||||||
fd = ret;
|
fd = ret;
|
||||||
|
|
||||||
if ((ret = virStorageBackendUpdateVolTargetInfoFD(target, fd,
|
if ((ret = virStorageBackendUpdateVolTargetInfoFD(target, fd,
|
||||||
allocation,
|
allocation,
|
||||||
capacity)) < 0) {
|
capacity)) < 0) {
|
||||||
VIR_FORCE_CLOSE(fd);
|
goto error;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&meta, 0, sizeof(meta));
|
|
||||||
|
|
||||||
if ((target->format = virStorageFileProbeFormatFromFD(target->path, fd)) < 0) {
|
if ((target->format = virStorageFileProbeFormatFromFD(target->path, fd)) < 0) {
|
||||||
VIR_FORCE_CLOSE(fd);
|
ret = -1;
|
||||||
return -1;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (virStorageFileGetMetadataFromFD(target->path, fd,
|
if (virStorageFileGetMetadataFromFD(target->path, fd,
|
||||||
target->format,
|
target->format,
|
||||||
&meta) < 0) {
|
meta) < 0) {
|
||||||
VIR_FORCE_CLOSE(fd);
|
ret = -1;
|
||||||
return -1;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
VIR_FORCE_CLOSE(fd);
|
VIR_FORCE_CLOSE(fd);
|
||||||
|
|
||||||
if (meta.backingStore) {
|
if (meta->backingStore) {
|
||||||
*backingStore = meta.backingStore;
|
*backingStore = meta->backingStore;
|
||||||
meta.backingStore = NULL;
|
meta->backingStore = NULL;
|
||||||
if (meta.backingStoreFormat == VIR_STORAGE_FILE_AUTO) {
|
if (meta->backingStoreFormat == VIR_STORAGE_FILE_AUTO) {
|
||||||
if ((ret = virStorageFileProbeFormat(*backingStore)) < 0) {
|
if ((ret = virStorageFileProbeFormat(*backingStore)) < 0) {
|
||||||
/* If the backing file is currently unavailable, only log an error,
|
/* If the backing file is currently unavailable, only log an error,
|
||||||
* but continue. Returning -1 here would disable the whole storage
|
* but continue. Returning -1 here would disable the whole storage
|
||||||
@ -114,18 +117,17 @@ virStorageBackendProbeTarget(virStorageVolTargetPtr target,
|
|||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
*backingStoreFormat = meta.backingStoreFormat;
|
*backingStoreFormat = meta->backingStoreFormat;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
VIR_FREE(meta.backingStore);
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (capacity && meta.capacity)
|
if (capacity && meta->capacity)
|
||||||
*capacity = meta.capacity;
|
*capacity = meta->capacity;
|
||||||
|
|
||||||
if (encryption != NULL && meta.encrypted) {
|
if (encryption != NULL && meta->encrypted) {
|
||||||
if (VIR_ALLOC(*encryption) < 0) {
|
if (VIR_ALLOC(*encryption) < 0) {
|
||||||
virReportOOMError();
|
virReportOOMError();
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -147,11 +149,17 @@ virStorageBackendProbeTarget(virStorageVolTargetPtr target,
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virStorageFileFreeMetadata(meta);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
error:
|
||||||
|
VIR_FORCE_CLOSE(fd);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
VIR_FREE(*backingStore);
|
virStorageFileFreeMetadata(meta);
|
||||||
return -1;
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if WITH_STORAGE_FS
|
#if WITH_STORAGE_FS
|
||||||
|
@ -819,6 +819,8 @@ virStorageFileProbeFormat(const char *path)
|
|||||||
* it indicates the image didn't specify an explicit format for its
|
* it indicates the image didn't specify an explicit format for its
|
||||||
* backing store. Callers are advised against probing for the
|
* backing store. Callers are advised against probing for the
|
||||||
* backing store format in this case.
|
* backing store format in this case.
|
||||||
|
*
|
||||||
|
* Caller MUST free @meta after use via virStorageFileFreeMetadata.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
virStorageFileGetMetadataFromFD(const char *path,
|
virStorageFileGetMetadataFromFD(const char *path,
|
||||||
@ -892,6 +894,8 @@ cleanup:
|
|||||||
* it indicates the image didn't specify an explicit format for its
|
* it indicates the image didn't specify an explicit format for its
|
||||||
* backing store. Callers are advised against probing for the
|
* backing store. Callers are advised against probing for the
|
||||||
* backing store format in this case.
|
* backing store format in this case.
|
||||||
|
*
|
||||||
|
* Caller MUST free @meta after use via virStorageFileFreeMetadata.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
virStorageFileGetMetadata(const char *path,
|
virStorageFileGetMetadata(const char *path,
|
||||||
@ -912,6 +916,20 @@ virStorageFileGetMetadata(const char *path,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virStorageFileFreeMetadata:
|
||||||
|
*
|
||||||
|
* Free pointers in passed structure and structure itself.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
virStorageFileFreeMetadata(virStorageFileMetadata *meta)
|
||||||
|
{
|
||||||
|
if (!meta)
|
||||||
|
return;
|
||||||
|
|
||||||
|
VIR_FREE(meta->backingStore);
|
||||||
|
VIR_FREE(meta);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
|
||||||
|
@ -70,6 +70,8 @@ int virStorageFileGetMetadataFromFD(const char *path,
|
|||||||
int format,
|
int format,
|
||||||
virStorageFileMetadata *meta);
|
virStorageFileMetadata *meta);
|
||||||
|
|
||||||
|
void virStorageFileFreeMetadata(virStorageFileMetadata *meta);
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
VIR_STORAGE_FILE_SHFS_NFS = (1 << 0),
|
VIR_STORAGE_FILE_SHFS_NFS = (1 << 0),
|
||||||
VIR_STORAGE_FILE_SHFS_GFS2 = (1 << 1),
|
VIR_STORAGE_FILE_SHFS_GFS2 = (1 << 1),
|
||||||
|
Loading…
Reference in New Issue
Block a user