virFindBackingFile(const char *start, const char *path,
char **directory, char **canonical)
{
+ /* FIXME - when we eventually allow non-raw network devices, we
+ * must ensure that we handle backing files the same way as qemu.
+ * For a qcow2 top file of gluster://server/vol/img, qemu treats
+ * the relative backing file 'rel' as meaning
+ * 'gluster://server/vol/rel', while the backing file '/abs' is
+ * used as a local file. But we cannot canonicalize network
+ * devices via canonicalize_file_name(), because they are not part
+ * of the local file system. */
char *combined = NULL;
int ret = -1;
meta->backingStoreRaw, path);
}
+ } else {
+ if (VIR_STRDUP(meta->backingStoreRaw, backing) < 0) {
+ VIR_FREE(backing);
+ goto cleanup;
+ }
+ backingFormat = VIR_STORAGE_FILE_RAW;
}
VIR_FREE(backing);
meta->backingStoreFormat = backingFormat;
if (virHashAddEntry(cycle, canonPath, (void *)1) < 0)
return -1;
- if ((fd = virFileOpenAs(canonPath, O_RDONLY, 0, uid, gid, 0)) < 0) {
- virReportSystemError(-fd, _("Failed to open file '%s'"), path);
- return -1;
- }
+ if (virBackingStoreIsFile(path)) {
+ if ((fd = virFileOpenAs(canonPath, O_RDONLY, 0, uid, gid, 0)) < 0) {
+ virReportSystemError(-fd, _("Failed to open file '%s'"), path);
+ return -1;
+ }
- ret = virStorageFileGetMetadataFromFDInternal(path, canonPath, directory,
- fd, format, meta);
+ ret = virStorageFileGetMetadataFromFDInternal(path, canonPath,
+ directory,
+ fd, format, meta);
- if (VIR_CLOSE(fd) < 0)
- VIR_WARN("could not close file %s", path);
+ if (VIR_CLOSE(fd) < 0)
+ VIR_WARN("could not close file %s", path);
+ } else {
+ /* FIXME: when the proper storage drivers are compiled in, it
+ * would be nice to read metadata from the network storage to
+ * allow for non-raw images. */
+ if (VIR_STRDUP(meta->path, path) < 0)
+ return -1;
+ if (VIR_STRDUP(meta->canonPath, path) < 0)
+ return -1;
+ meta->type = VIR_STORAGE_TYPE_NETWORK;
+ meta->format = VIR_STORAGE_FILE_RAW;
+ ret = 0;
+ }
- if (ret == 0 && meta->backingStoreIsFile) {
+ if (ret == 0 && meta->backingStore) {
virStorageFileMetadataPtr backing;
if (meta->backingStoreFormat == VIR_STORAGE_FILE_AUTO && !allow_probe)
if (!cycle)
return NULL;
- if (!(canonPath = canonicalize_file_name(path))) {
- virReportSystemError(errno, _("unable to resolve '%s'"), path);
- goto cleanup;
- }
- if (!(directory = mdir_name(path))) {
- virReportOOMError();
+ if (virBackingStoreIsFile(path)) {
+ if (!(canonPath = canonicalize_file_name(path))) {
+ virReportSystemError(errno, _("unable to resolve '%s'"), path);
+ goto cleanup;
+ }
+ if (!(directory = mdir_name(path))) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ } else if (VIR_STRDUP(canonPath, path) < 0) {
goto cleanup;
}
if (VIR_ALLOC(meta) < 0)
*
* 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.
+ * Return 0 on success (including when brokenFile is set), negative on
+ * error (allocation failure).
*/
int
virStorageFileChainGetBroken(virStorageFileMetadataPtr chain,
virStorageFileMetadataPtr tmp;
int ret = -1;
+ *brokenFile = NULL;
+
if (!chain)
return 0;
- *brokenFile = NULL;
-
tmp = chain;
while (tmp) {
- /* Break if no backing store, backing store is not file, or
- * other problem such as infinite loop */
+ /* Break when we hit end of chain; report error if we detected
+ * a missing backing file, infinite loop, or other error */
if (!tmp->backingStoreRaw)
break;
if (!tmp->backingStore) {
if (virCommandRun(cmd, NULL) < 0)
ret = -1;
qcow2.expBackingStore = "nbd:example.org:6000";
- qcow2.expBackingStoreRaw = NULL;
+ qcow2.expBackingStoreRaw = "nbd:example.org:6000";
qcow2.expBackingDirRel = NULL;
qcow2.expBackingDirAbs = NULL;
qcow2.expBackingFormat = VIR_STORAGE_FILE_RAW;
/* Qcow2 file with backing protocol instead of file */
+ testFileData nbd = {
+ .pathRel = "nbd:example.org:6000",
+ .pathAbs = "nbd:example.org:6000",
+ .canonPath = "nbd:example.org:6000",
+ .type = VIR_STORAGE_TYPE_NETWORK,
+ .format = VIR_STORAGE_FILE_RAW,
+ };
TEST_CHAIN(11, "qcow2", absqcow2, VIR_STORAGE_FILE_QCOW2,
- (&qcow2), EXP_PASS,
- (&qcow2), ALLOW_PROBE | EXP_PASS,
- (&qcow2), EXP_PASS,
- (&qcow2), ALLOW_PROBE | EXP_PASS);
+ (&qcow2, &nbd), EXP_PASS,
+ (&qcow2, &nbd), ALLOW_PROBE | EXP_PASS,
+ (&qcow2, &nbd), EXP_PASS,
+ (&qcow2, &nbd), ALLOW_PROBE | EXP_PASS);
/* qed file */
testFileData qed = {