diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 96277cd8f0..143266de5b 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3073,7 +3073,9 @@ static int qemuSetupDiskCgroup(virCgroupPtr cgroup, } } - rc = virStorageFileGetMetadata(path, &meta); + rc = virStorageFileGetMetadata(path, + VIR_STORAGE_FILE_AUTO, + &meta); if (rc < 0) VIR_WARN("Unable to lookup parent image for %s", path); @@ -3123,7 +3125,9 @@ static int qemuTeardownDiskCgroup(virCgroupPtr cgroup, } } - rc = virStorageFileGetMetadata(path, &meta); + rc = virStorageFileGetMetadata(path, + VIR_STORAGE_FILE_AUTO, + &meta); if (rc < 0) VIR_WARN("Unable to lookup parent image for %s", path); @@ -9618,6 +9622,7 @@ static int qemuDomainGetBlockInfo(virDomainPtr dom, virDomainDiskDefPtr disk = NULL; struct stat sb; int i; + int format; virCheckFlags(0, -1); @@ -9662,7 +9667,21 @@ static int qemuDomainGetBlockInfo(virDomainPtr dom, } /* Probe for magic formats */ - if (virStorageFileGetMetadataFromFD(path, fd, &meta) < 0) + if (disk->driverType) { + if ((format = virStorageFileFormatTypeFromString(disk->driverType)) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("unknown disk format %s for %s"), + disk->driverType, disk->src); + goto cleanup; + } + } else { + if ((format = virStorageFileProbeFormat(disk->src)) < 0) + goto cleanup; + } + + if (virStorageFileGetMetadataFromFD(path, fd, + format, + &meta) < 0) goto cleanup; /* Get info for normal formats */ @@ -9710,7 +9729,7 @@ static int qemuDomainGetBlockInfo(virDomainPtr dom, highest allocated extent from QEMU */ if (virDomainObjIsActive(vm) && disk->type == VIR_DOMAIN_DISK_TYPE_BLOCK && - meta.format != VIR_STORAGE_FILE_RAW && + format != VIR_STORAGE_FILE_RAW && S_ISBLK(sb.st_mode)) { qemuDomainObjPrivatePtr priv = vm->privateData; if (qemuDomainObjBeginJob(vm) < 0) diff --git a/src/qemu/qemu_security_dac.c b/src/qemu/qemu_security_dac.c index 95015b091b..acfe48eff8 100644 --- a/src/qemu/qemu_security_dac.c +++ b/src/qemu/qemu_security_dac.c @@ -115,7 +115,9 @@ qemuSecurityDACSetSecurityImageLabel(virDomainObjPtr vm ATTRIBUTE_UNUSED, virStorageFileMetadata meta; int ret; - ret = virStorageFileGetMetadata(path, &meta); + ret = virStorageFileGetMetadata(path, + VIR_STORAGE_FILE_AUTO, + &meta); if (path != disk->src) VIR_FREE(path); diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index e5eef196d1..5c0f002dc6 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -457,7 +457,9 @@ SELinuxSetSecurityImageLabel(virDomainObjPtr vm, virStorageFileMetadata meta; int ret; - ret = virStorageFileGetMetadata(path, &meta); + ret = virStorageFileGetMetadata(path, + VIR_STORAGE_FILE_AUTO, + &meta); if (path != disk->src) VIR_FREE(path); diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c index c66f1075c7..2c045e67cd 100644 --- a/src/security/virt-aa-helper.c +++ b/src/security/virt-aa-helper.c @@ -830,7 +830,9 @@ get_files(vahControl * ctl) do { virStorageFileMetadata meta; - ret = virStorageFileGetMetadata(path, &meta); + ret = virStorageFileGetMetadata(path, + VIR_STORAGE_FILE_AUTO, + &meta); if (path != ctl->def->disks[i]->src) VIR_FREE(path); diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c index f0cd77040a..d3ac0fee3e 100644 --- a/src/storage/storage_backend_fs.c +++ b/src/storage/storage_backend_fs.c @@ -75,15 +75,20 @@ virStorageBackendProbeTarget(virStorageVolTargetPtr target, memset(&meta, 0, sizeof(meta)); - if (virStorageFileGetMetadataFromFD(target->path, fd, &meta) < 0) { + if ((target->format = virStorageFileProbeFormatFromFD(target->path, fd)) < 0) { + close(fd); + return -1; + } + + if (virStorageFileGetMetadataFromFD(target->path, fd, + target->format, + &meta) < 0) { close(fd); return -1; } close(fd); - target->format = meta.format; - if (backingStore) { *backingStore = meta.backingStore; meta.backingStore = NULL; diff --git a/src/util/storage_file.c b/src/util/storage_file.c index bfc26d81d2..3cd5dbcf8d 100644 --- a/src/util/storage_file.c +++ b/src/util/storage_file.c @@ -696,18 +696,23 @@ virStorageFileProbeFormat(const char *path) /** * virStorageFileGetMetadataFromFD: * - * Probe for the format of 'fd' (which is an open file descriptor - * for the file 'path'), filling 'meta' with the detected - * format and other associated metadata. + * Extract metadata about the storage volume with the specified + * image format. If image format is VIR_STORAGE_FILE_AUTO, it + * will probe to automatically identify the format. * - * Callers are advised never to trust the returned 'meta->format' - * unless it is listed as VIR_STORAGE_FILE_RAW, since a - * malicious guest can turn a raw file into any other non-raw - * format at will. + * Callers are advised never to use VIR_STORAGE_FILE_AUTO as a + * format, since a malicious guest can turn a raw file into any + * other non-raw format at will. + * + * If the returned meta.backingStoreFormat is VIR_STORAGE_FILE_AUTO + * it indicates the image didn't specify an explicit format for its + * backing store. Callers are advised against probing for the + * backing store format in this case. */ int virStorageFileGetMetadataFromFD(const char *path, int fd, + int format, virStorageFileMetadata *meta) { unsigned char *head; @@ -731,9 +736,16 @@ virStorageFileGetMetadataFromFD(const char *path, goto cleanup; } - meta->format = virStorageFileProbeFormatFromBuf(path, head, len); + if (format == VIR_STORAGE_FILE_AUTO) + format = virStorageFileProbeFormatFromBuf(path, head, len); - ret = virStorageFileGetMetadataFromBuf(meta->format, path, head, len, meta); + if (format < 0 || + format >= VIR_STORAGE_FILE_LAST) { + virReportSystemError(EINVAL, _("unknown storage file format %d"), format); + return -1; + } + + ret = virStorageFileGetMetadataFromBuf(format, path, head, len, meta); cleanup: VIR_FREE(head); @@ -743,16 +755,22 @@ cleanup: /** * virStorageFileGetMetadata: * - * Probe for the format of 'path', filling 'meta' with the detected - * format and other associated metadata. + * Extract metadata about the storage volume with the specified + * image format. If image format is VIR_STORAGE_FILE_AUTO, it + * will probe to automatically identify the format. * - * Callers are advised never to trust the returned 'meta->format' - * unless it is listed as VIR_STORAGE_FILE_RAW, since a - * malicious guest can turn a raw file into any other non-raw - * format at will. + * Callers are advised never to use VIR_STORAGE_FILE_AUTO as a + * format, since a malicious guest can turn a raw file into any + * other non-raw format at will. + * + * If the returned meta.backingStoreFormat is VIR_STORAGE_FILE_AUTO + * it indicates the image didn't specify an explicit format for its + * backing store. Callers are advised against probing for the + * backing store format in this case. */ int virStorageFileGetMetadata(const char *path, + int format, virStorageFileMetadata *meta) { int fd, ret; @@ -762,7 +780,7 @@ virStorageFileGetMetadata(const char *path, return -1; } - ret = virStorageFileGetMetadataFromFD(path, fd, meta); + ret = virStorageFileGetMetadataFromFD(path, fd, format, meta); close(fd); diff --git a/src/util/storage_file.h b/src/util/storage_file.h index 3420d44801..6853182f78 100644 --- a/src/util/storage_file.h +++ b/src/util/storage_file.h @@ -46,7 +46,6 @@ enum virStorageFileFormat { VIR_ENUM_DECL(virStorageFileFormat); typedef struct _virStorageFileMetadata { - int format; char *backingStore; int backingStoreFormat; unsigned long long capacity; @@ -62,9 +61,11 @@ int virStorageFileProbeFormatFromFD(const char *path, int fd); int virStorageFileGetMetadata(const char *path, + int format, virStorageFileMetadata *meta); int virStorageFileGetMetadataFromFD(const char *path, int fd, + int format, virStorageFileMetadata *meta); int virStorageFileIsSharedFS(const char *path);