- parse data-file metadata and init src->dataFileStore struct
- chown data-file to allow qemu to open it
- add data-file path to VM's cgroup and namespace
- add data-file option to QEMU process command line
Signed-off-by: Nikolai Barybin <nikolai.barybin(a)virtuozzo.com>
---
src/qemu/qemu_block.c | 45 +++++++++++++++++++++++++++++++
src/qemu/qemu_cgroup.c | 3 +++
src/qemu/qemu_namespace.c | 6 +++++
src/storage_file/storage_source.c | 38 ++++++++++++++++++++++++--
4 files changed, 90 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index d6cdf521c4..38f4717d56 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -1271,6 +1271,48 @@ qemuBlockStorageSourceGetFormatQcowGenericProps(virStorageSource
*src,
}
+static int
+qemuBlockStorageGetQcow2DataFileProps(virStorageSource *src,
+ virJSONValue *props)
+{
+ g_autoptr(virJSONValue) dataFileDef = NULL;
+ virStorageType actualType;
+ g_autofree char *driverName = NULL;
+
+ if (!src->dataFileRaw)
+ return 0;
+
+ actualType = virStorageSourceGetActualType(src->dataFileStore);
+ if (actualType != VIR_STORAGE_TYPE_BLOCK &&
+ actualType != VIR_STORAGE_TYPE_FILE) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("%1$s storage type is not supported for qcow2
data-file"),
+ NULLSTR(virStorageTypeToString(actualType)));
+ return -1;
+ }
+
+ if (virStorageSourceIsBlockLocal(src->dataFileStore))
+ driverName = g_strdup("host_device");
+ else
+ driverName = g_strdup("file");
+
+ if (virJSONValueObjectAdd(&dataFileDef,
+ "s:driver", driverName,
+ "b:read-only", src->readonly,
+ "s:filename", src->dataFileRaw,
+ NULL) < 0)
+ return -1;
+
+ if (virJSONValueObjectAdd(&props,
+ "A:data-file", &dataFileDef,
+ NULL) < 0)
+ return -1;
+
+ return 0;
+}
+
+
+
static int
qemuBlockStorageSourceGetFormatQcow2Props(virStorageSource *src,
virJSONValue *props)
@@ -1301,6 +1343,9 @@ qemuBlockStorageSourceGetFormatQcow2Props(virStorageSource *src,
NULL) < 0)
return -1;
+ if (qemuBlockStorageGetQcow2DataFileProps(src, props) < 0)
+ return -1;
+
return 0;
}
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index 23b7e6b4e8..84c749b567 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -223,6 +223,9 @@ qemuSetupImageCgroupInternal(virDomainObj *vm,
qemuSetupImagePathCgroup(vm, QEMU_DEVICE_MAPPER_CONTROL_PATH, false) < 0)
return -1;
+ if (src->dataFileRaw && qemuSetupImagePathCgroup(vm, src->dataFileRaw,
readonly) < 0)
+ return -1;
+
return qemuSetupImagePathCgroup(vm, path, readonly);
}
diff --git a/src/qemu/qemu_namespace.c b/src/qemu/qemu_namespace.c
index bbe3d5a1f7..32653443ec 100644
--- a/src/qemu/qemu_namespace.c
+++ b/src/qemu/qemu_namespace.c
@@ -290,6 +290,12 @@ qemuDomainSetupDisk(virStorageSource *src,
if (targetPaths)
*paths = g_slist_concat(g_slist_reverse(targetPaths), *paths);
+
+ if (next->dataFileRaw) {
+ g_autofree char *datafile = NULL;
+ datafile = g_strdup(next->dataFileRaw);
+ *paths = g_slist_prepend(*paths, g_steal_pointer(&datafile));
+ }
}
*paths = g_slist_prepend(*paths, g_steal_pointer(&tmpPath));
diff --git a/src/storage_file/storage_source.c b/src/storage_file/storage_source.c
index 2cfe3bc325..0ea11228d4 100644
--- a/src/storage_file/storage_source.c
+++ b/src/storage_file/storage_source.c
@@ -1378,8 +1378,16 @@ virStorageSourceGetMetadataRecurse(virStorageSource *src,
&buf, &headerLen) < 0)
return -1;
- if (virStorageFileProbeGetMetadata(src, buf, headerLen) < 0)
- return -1;
+ if (!parent->dataFileRaw) {
+ if (virStorageFileProbeGetMetadata(src, buf, headerLen) < 0)
+ return -1;
+ } else {
+ if (virStorageSourceInitAs(src, uid, gid) < 0)
+ return -1;
+ if (virStorageSourceChown(src, uid, gid) < 0)
+ return -1;
+ virStorageSourceDeinit(src);
+ }
/* If we probed the format we MUST ensure that nothing else than the current
* image is considered for security labelling and/or recursion. */
@@ -1417,6 +1425,32 @@ virStorageSourceGetMetadataRecurse(virStorageSource *src,
backingStore->id = depth;
src->backingStore = g_steal_pointer(&backingStore);
+
+ } else if (src->dataFileRaw) {
+ if ((rv = virStorageSourceNewFromChild(src, src->dataFileRaw,
&backingStore)) < 0)
+ return -1;
+
+ if (rv == 1)
+ return 0;
+
+ if ((rv = virStorageSourceGetMetadataRecurse(backingStore, parent,
+ uid, gid,
+ report_broken,
+ max_depth, depth + 1)) < 0) {
+ if (!report_broken)
+ return 0;
+
+ if (rv == -2) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("format of data file image '%1$s' of image
'%2$s' was not specified in the image metadata (See
https://libvirt.org/kbase/backing_chains.html for troubleshooting)"),
+ src->dataFileRaw, NULLSTR(src->path));
+ }
+
+ return -1;
+ }
+
+ backingStore->id = depth;
+ src->dataFileStore = g_steal_pointer(&backingStore);
} else {
/* add terminator */
src->backingStore = virStorageSourceNew();
--
2.43.5