So far, my work has been merely preserving the status quo of backing file analysis. But this patch starts to tread in the territory of making the backing chain code more powerful - we will eventually support network storage containing non-raw formats. Here, we expose metadata information about a network backing store, even if that information is still hardcoded to a raw format for now. * src/util/virstoragefile.c (virStorageFileGetMetadataRecurse): Also populate struct for non-file backing. (virStorageFileGetMetadata, virStorageFileGetMetadatainternal): Recognize non-file top image. (virFindBackingFile): Add comment. * tests/virstoragetest.c (mymain): Update test to reflect it. Signed-off-by: Eric Blake <eblake@xxxxxxxxxx> --- src/util/virstoragefile.c | 62 +++++++++++++++++++++++++++++++++++------------ tests/virstoragetest.c | 17 +++++++++---- 2 files changed, 59 insertions(+), 20 deletions(-) diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index f5fe8ad..7a91a01 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -569,6 +569,14 @@ static int ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4) 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; @@ -874,6 +882,12 @@ virStorageFileGetMetadataInternal(const char *path, 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; @@ -1132,18 +1146,32 @@ virStorageFileGetMetadataRecurse(const char *path, const char *canonPath, 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) @@ -1207,12 +1235,16 @@ virStorageFileGetMetadata(const char *path, int format, 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) diff --git a/tests/virstoragetest.c b/tests/virstoragetest.c index 9a9b0d8..e8409f6 100644 --- a/tests/virstoragetest.c +++ b/tests/virstoragetest.c @@ -621,17 +621,24 @@ mymain(void) 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 = { -- 1.9.0 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list