Domain snapshots should only permit an external snapshot into a storage format that permits a backing chain, since the new snapshot file necessarily must be backed by the existing file. The C code for the qemu driver is a little bit stricter in currently enforcing only qcow2 or qed, but at the XML parser level, including virt-xml-validate, it is fairly easy to enforce that a user can't request a 'raw' external snapshot. * docs/schemas/storagecommon.rng (storageFormat): Split out... (storageFormatBacking): ...new sublist. * docs/schemas/domainsnapshot.rng (disksnapshotdriver): Use new type. * src/util/virstoragefile.h (virStorageFileFormat): Rearrange for easier code management. * src/util/virstoragefile.c (virStorageFileFormat, fileTypeInfo): Likewise. * src/conf/snapshot_conf.c (virDomainSnapshotDiskDefParseXML): Use new marker to limit selection of formats. Signed-off-by: Eric Blake <eblake@xxxxxxxxxx> --- docs/schemas/domainsnapshot.rng | 2 +- docs/schemas/storagecommon.rng | 17 ++++++++++---- src/conf/snapshot_conf.c | 7 ++++-- src/util/virstoragefile.c | 51 ++++++++++++++++++++++------------------- src/util/virstoragefile.h | 15 ++++++++---- 5 files changed, 55 insertions(+), 37 deletions(-) diff --git a/docs/schemas/domainsnapshot.rng b/docs/schemas/domainsnapshot.rng index 824a186..644da90 100644 --- a/docs/schemas/domainsnapshot.rng +++ b/docs/schemas/domainsnapshot.rng @@ -184,7 +184,7 @@ <element name='driver'> <optional> <attribute name='type'> - <ref name='storageFormat'/> + <ref name='storageFormatBacking'/> </attribute> </optional> <empty/> diff --git a/docs/schemas/storagecommon.rng b/docs/schemas/storagecommon.rng index 37b43c6..2d61abc 100644 --- a/docs/schemas/storagecommon.rng +++ b/docs/schemas/storagecommon.rng @@ -52,23 +52,30 @@ </element> </define> + <!-- split the list of known storage formats into two, those where + we know how to follow backing chains, and all others --> + <define name='storageFormatBacking'> + <choice> + <value>cow</value> + <value>qcow</value> + <value>qcow2</value> + <value>qed</value> + <value>vmdk</value> + </choice> + </define> <define name='storageFormat'> <choice> <value>raw</value> <value>dir</value> <value>bochs</value> <value>cloop</value> - <value>cow</value> <value>dmg</value> <value>iso</value> - <value>qcow</value> - <value>qcow2</value> - <value>qed</value> - <value>vmdk</value> <value>vpc</value> <value>fat</value> <value>vhd</value> <value>vdi</value> + <ref name='storageFormatBacking'/> </choice> </define> diff --git a/src/conf/snapshot_conf.c b/src/conf/snapshot_conf.c index 070e50d..b0e4700 100644 --- a/src/conf/snapshot_conf.c +++ b/src/conf/snapshot_conf.c @@ -158,9 +158,12 @@ virDomainSnapshotDiskDefParseXML(xmlNodePtr node, char *driver = virXMLPropString(cur, "type"); if (driver) { def->src.format = virStorageFileFormatTypeFromString(driver); - if (def->src.format <= 0) { + if (def->src.format < VIR_STORAGE_FILE_BACKING) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("unknown disk snapshot driver '%s'"), + def->src.format <= 0 + ? _("unknown disk snapshot driver '%s'") + : _("disk format '%s' lacks backing file " + "support"), driver); VIR_FREE(driver); goto cleanup; diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index 94dddbc..42e9865 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -59,9 +59,10 @@ VIR_ENUM_IMPL(virStorageFileFormat, VIR_STORAGE_FILE_LAST, "none", "raw", "dir", "bochs", - "cloop", "cow", "dmg", "iso", - "qcow", "qcow2", "qed", "vmdk", "vpc", - "fat", "vhd", "vdi") + "cloop", "dmg", "iso", + "vpc", "fat", "vhd", "vdi", + /* Formats with backing file below here */ + "cow", "qcow", "qcow2", "qed", "vmdk") VIR_ENUM_IMPL(virStorageFileFeature, VIR_STORAGE_FILE_FEATURE_LAST, @@ -198,11 +199,6 @@ static struct FileTypeInfo const fileTypeInfo[] = { LV_LITTLE_ENDIAN, -1, {0}, -1, 0, 0, -1, NULL, NULL }, - [VIR_STORAGE_FILE_COW] = { - 0, "OOOM", NULL, - LV_BIG_ENDIAN, 4, {2}, - 4+4+1024+4, 8, 1, -1, cowGetBackingStore, NULL - }, [VIR_STORAGE_FILE_DMG] = { /* XXX QEMU says there's no magic for dmg, * /usr/share/misc/magic lists double magic (both offsets @@ -216,6 +212,29 @@ static struct FileTypeInfo const fileTypeInfo[] = { LV_LITTLE_ENDIAN, -2, {0}, -1, 0, 0, -1, NULL, NULL }, + [VIR_STORAGE_FILE_VPC] = { + 0, "conectix", NULL, + LV_BIG_ENDIAN, 12, {0x10000}, + 8 + 4 + 4 + 8 + 4 + 4 + 2 + 2 + 4, 8, 1, -1, NULL, NULL + }, + /* TODO: add getBackingStore function */ + [VIR_STORAGE_FILE_VDI] = { + 64, "\x7f\x10\xda\xbe", ".vdi", + LV_LITTLE_ENDIAN, 68, {0x00010001}, + 64 + 5 * 4 + 256 + 7 * 4, 8, 1, -1, NULL, NULL}, + + /* Not direct file formats, but used for various drivers */ + [VIR_STORAGE_FILE_FAT] = { 0, NULL, NULL, LV_LITTLE_ENDIAN, + -1, {0}, 0, 0, 0, 0, NULL, NULL }, + [VIR_STORAGE_FILE_VHD] = { 0, NULL, NULL, LV_LITTLE_ENDIAN, + -1, {0}, 0, 0, 0, 0, NULL, NULL }, + + /* All formats with a backing store probe below here */ + [VIR_STORAGE_FILE_COW] = { + 0, "OOOM", NULL, + LV_BIG_ENDIAN, 4, {2}, + 4+4+1024+4, 8, 1, -1, cowGetBackingStore, NULL + }, [VIR_STORAGE_FILE_QCOW] = { 0, "QFI", NULL, LV_BIG_ENDIAN, 4, {1}, @@ -238,22 +257,6 @@ static struct FileTypeInfo const fileTypeInfo[] = { LV_LITTLE_ENDIAN, 4, {1, 2}, 4+4+4, 8, 512, -1, vmdk4GetBackingStore, NULL }, - [VIR_STORAGE_FILE_VPC] = { - 0, "conectix", NULL, - LV_BIG_ENDIAN, 12, {0x10000}, - 8 + 4 + 4 + 8 + 4 + 4 + 2 + 2 + 4, 8, 1, -1, NULL, NULL - }, - /* TODO: add getBackingStore function */ - [VIR_STORAGE_FILE_VDI] = { - 64, "\x7f\x10\xda\xbe", ".vdi", - LV_LITTLE_ENDIAN, 68, {0x00010001}, - 64 + 5 * 4 + 256 + 7 * 4, 8, 1, -1, NULL, NULL}, - - /* Not direct file formats, but used for various drivers */ - [VIR_STORAGE_FILE_FAT] = { 0, NULL, NULL, LV_LITTLE_ENDIAN, - -1, {0}, 0, 0, 0, 0, NULL, NULL }, - [VIR_STORAGE_FILE_VHD] = { 0, NULL, NULL, LV_LITTLE_ENDIAN, - -1, {0}, 0, 0, 0, 0, NULL, NULL }, }; verify(ARRAY_CARDINALITY(fileTypeInfo) == VIR_STORAGE_FILE_LAST); diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h index 55ea890..29f93c1 100644 --- a/src/util/virstoragefile.h +++ b/src/util/virstoragefile.h @@ -64,18 +64,23 @@ enum virStorageFileFormat { VIR_STORAGE_FILE_DIR, VIR_STORAGE_FILE_BOCHS, VIR_STORAGE_FILE_CLOOP, - VIR_STORAGE_FILE_COW, VIR_STORAGE_FILE_DMG, VIR_STORAGE_FILE_ISO, - VIR_STORAGE_FILE_QCOW, - VIR_STORAGE_FILE_QCOW2, - VIR_STORAGE_FILE_QED, - VIR_STORAGE_FILE_VMDK, VIR_STORAGE_FILE_VPC, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD, VIR_STORAGE_FILE_VDI, + /* Not a format, but a marker: all formats below this point have + * libvirt support for following a backing chain */ + VIR_STORAGE_FILE_BACKING, + + VIR_STORAGE_FILE_COW = VIR_STORAGE_FILE_BACKING, + VIR_STORAGE_FILE_QCOW, + VIR_STORAGE_FILE_QCOW2, + VIR_STORAGE_FILE_QED, + VIR_STORAGE_FILE_VMDK, + VIR_STORAGE_FILE_LAST, }; -- 1.9.0 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list