From d7b7aa2c206951bef3b1bfece656394d1775cb7d Mon Sep 17 00:00:00 2001 From: Guannan Ren Date: Mon, 29 Jul 2013 20:51:15 +0800 Subject: [PATCH] qemu: add helper functions for diskchain checking *src/util/virstoragefile.c: Add a helper function to get the first name of missing backing files, if the name is NULL, it means the diskchain is not broken. *src/qemu/qemu_domain.c: qemuDiskChainCheckBroken(disk) to check if its chain is broken --- src/libvirt_private.syms | 1 + src/qemu/qemu_domain.c | 22 +++++++++++++++++++ src/qemu/qemu_domain.h | 3 +++ src/util/virstoragefile.c | 46 +++++++++++++++++++++++++++++++++++++++ src/util/virstoragefile.h | 2 ++ 5 files changed, 74 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 6e6e280f8c..a958d94436 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1883,6 +1883,7 @@ virSocketAddrSetPort; # util/virstoragefile.h +virStorageFileChainGetBroken; virStorageFileChainLookup; virStorageFileFeatureTypeFromString; virStorageFileFeatureTypeToString; diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 03a2aa6c73..be779918bd 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -2186,6 +2186,28 @@ qemuDomainCleanupRun(virQEMUDriverPtr driver, priv->ncleanupCallbacks_max = 0; } +int +qemuDiskChainCheckBroken(virDomainDiskDefPtr disk) +{ + char *brokenFile = NULL; + + if (!disk->src || !disk->backingChain) + return 0; + + if (virStorageFileChainGetBroken(disk->backingChain, &brokenFile) < 0) + return -1; + + if (brokenFile) { + virReportError(VIR_ERR_INVALID_ARG, + _("Backing file '%s' of image '%s' is missing."), + brokenFile, disk->src); + VIR_FREE(brokenFile); + return -1; + } + + return 0; +} + int qemuDomainDetermineDiskChain(virQEMUDriverPtr driver, virDomainDiskDefPtr disk, diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 9a959d6ec0..0a4a51ec4e 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -347,6 +347,9 @@ bool qemuDomainJobAllowed(qemuDomainObjPrivatePtr priv, int qemuDomainCheckDiskPresence(virQEMUDriverPtr driver, virDomainObjPtr vm, bool start_with_state); + +int qemuDiskChainCheckBroken(virDomainDiskDefPtr disk); + int qemuDomainDetermineDiskChain(virQEMUDriverPtr driver, virDomainDiskDefPtr disk, bool force); diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index cb6df91642..0b9cec3b04 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -572,6 +572,13 @@ virFindBackingFile(const char *start, bool start_is_dir, const char *path, goto cleanup; } + if (virFileAccessibleAs(combined, F_OK, getuid(), getgid()) < 0) { + virReportSystemError(errno, + _("Cannot access backing file '%s'"), + combined); + goto cleanup; + } + if (!(*canonical = canonicalize_file_name(combined))) { virReportSystemError(errno, _("Can't canonicalize path '%s'"), path); @@ -1096,6 +1103,45 @@ virStorageFileGetMetadata(const char *path, int format, return ret; } +/** + * virStorageFileChainCheckBroken + * + * If CHAIN is broken, set *brokenFile to the broken file name, + * otherwise set it to NULL. Caller MUST free *brokenFile after use. + * Return 0 on success, negative on error. + */ +int +virStorageFileChainGetBroken(virStorageFileMetadataPtr chain, + char **brokenFile) +{ + virStorageFileMetadataPtr tmp; + int ret = -1; + + if (!chain) + return 0; + + *brokenFile = NULL; + + tmp = chain; + while (tmp) { + /* Break if no backing store or backing store is not file */ + if (!tmp->backingStoreRaw) + break; + if (!tmp->backingStore) { + if (VIR_STRDUP(*brokenFile, tmp->backingStoreRaw) < 0) + goto error; + break; + } + tmp = tmp->backingMeta; + } + + ret = 0; + +error: + return ret; +} + + /** * virStorageFileFreeMetadata: * diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h index 4cb47e6240..1f89839b09 100644 --- a/src/util/virstoragefile.h +++ b/src/util/virstoragefile.h @@ -90,6 +90,8 @@ virStorageFileMetadataPtr virStorageFileGetMetadata(const char *path, virStorageFileMetadataPtr virStorageFileGetMetadataFromFD(const char *path, int fd, int format); +int virStorageFileChainGetBroken(virStorageFileMetadataPtr chain, + char **broken_file); const char *virStorageFileChainLookup(virStorageFileMetadataPtr chain, const char *start,