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(a)redhat.com>
---
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