On Mon 29 Jul 2013 02:51:15 PM CEST, Guannan Ren wrote: > *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 d9615ea..f7166d6 100644 > --- a/src/libvirt_private.syms > +++ b/src/libvirt_private.syms > @@ -1882,6 +1882,7 @@ virSocketAddrSetPort; > > > # util/virstoragefile.h > +virStorageFileChainGetBroken; > virStorageFileChainLookup; > virStorageFileFeatureTypeFromString; > virStorageFileFeatureTypeToString; > diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c > index 03a2aa6..be77991 100644 > --- a/src/qemu/qemu_domain.c > +++ b/src/qemu/qemu_domain.c > @@ -2187,6 +2187,28 @@ qemuDomainCleanupRun(virQEMUDriverPtr driver, > } > > 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, > bool force) > diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h > index 9a959d6..0a4a51e 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 cb6df91..0b9cec3 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); > @@ -1097,6 +1104,45 @@ virStorageFileGetMetadata(const char *path, int format, > } > > /** > + * 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: > * > * Free pointers in passed structure and structure itself. > diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h > index 4cb47e6..1f89839 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, ACK, Martin -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list