]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: Add support for slices of type 'storage'
authorPeter Krempa <pkrempa@redhat.com>
Mon, 10 Feb 2020 13:37:14 +0000 (14:37 +0100)
committerPeter Krempa <pkrempa@redhat.com>
Fri, 14 Feb 2020 15:32:21 +0000 (16:32 +0100)
Implement support for the slice of type 'storage' which allows to set
the offset and size which modifies where qemu should look for the start
of the format container inside the image.

Since slicing is done using the 'raw' driver we need to add another
layer into the blockdev tree if there's any non-raw image format driver
used to access the data.

This patch adds the blockdev integration and setup of the image data so
that we can use the slices for any backing image.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
src/qemu/qemu_block.c
src/qemu/qemu_block.h
src/qemu/qemu_blockjob.c
src/qemu/qemu_command.c
src/qemu/qemu_domain.c

index 387a2db2e64c646b2189abdfef98562b678070e7..5bd5c955a4813b41d18c29f4fd582fdc39801660 100644 (file)
@@ -1423,11 +1423,16 @@ qemuBlockStorageSourceGetBlockdevProps(virStorageSourcePtr src,
                                        virStorageSourcePtr backingStore)
 {
     g_autoptr(virJSONValue) props = NULL;
+    const char *storagenode = src->nodestorage;
+
+    if (src->sliceStorage &&
+        src->format != VIR_STORAGE_FILE_RAW)
+        storagenode = src->sliceStorage->nodename;
 
     if (!(props = qemuBlockStorageSourceGetBlockdevFormatProps(src)))
         return NULL;
 
-    if (virJSONValueObjectAppendString(props, "file", src->nodestorage) < 0)
+    if (virJSONValueObjectAppendString(props, "file", storagenode) < 0)
         return NULL;
 
     if (backingStore) {
@@ -1456,6 +1461,32 @@ qemuBlockStorageSourceGetBlockdevProps(virStorageSourcePtr src,
 }
 
 
+static virJSONValuePtr
+qemuBlockStorageSourceGetBlockdevStorageSliceProps(virStorageSourcePtr src)
+{
+    g_autoptr(virJSONValue) props = NULL;
+
+    if (qemuBlockNodeNameValidate(src->sliceStorage->nodename) < 0)
+        return NULL;
+
+    if (virJSONValueObjectCreate(&props,
+                                 "s:driver", "raw",
+                                 "s:node-name", src->sliceStorage->nodename,
+                                 "U:offset", src->sliceStorage->offset,
+                                 "U:size", src->sliceStorage->size,
+                                 "s:file", src->nodestorage,
+                                 "b:auto-read-only", true,
+                                 "s:discard", "unmap",
+                                 NULL) < 0)
+        return NULL;
+
+    if (qemuBlockStorageSourceGetBlockdevGetCacheProps(src, props) < 0)
+        return NULL;
+
+    return g_steal_pointer(&props);
+}
+
+
 void
 qemuBlockStorageSourceAttachDataFree(qemuBlockStorageSourceAttachDataPtr data)
 {
@@ -1463,6 +1494,7 @@ qemuBlockStorageSourceAttachDataFree(qemuBlockStorageSourceAttachDataPtr data)
         return;
 
     virJSONValueFree(data->storageProps);
+    virJSONValueFree(data->storageSliceProps);
     virJSONValueFree(data->formatProps);
     virJSONValueFree(data->prmgrProps);
     virJSONValueFree(data->authsecretProps);
@@ -1513,6 +1545,13 @@ qemuBlockStorageSourceAttachPrepareBlockdev(virStorageSourcePtr src,
     data->storageNodeName = src->nodestorage;
     data->formatNodeName = src->nodeformat;
 
+    if (src->sliceStorage && src->format != VIR_STORAGE_FILE_RAW) {
+        if (!(data->storageSliceProps = qemuBlockStorageSourceGetBlockdevStorageSliceProps(src)))
+            return NULL;
+
+        data->storageSliceNodeName = src->sliceStorage->nodename;
+    }
+
     return g_steal_pointer(&data);
 }
 
@@ -1581,6 +1620,21 @@ qemuBlockStorageSourceAttachApplyFormat(qemuMonitorPtr mon,
 }
 
 
+static int
+qemuBlockStorageSourceAttachApplyStorageSlice(qemuMonitorPtr mon,
+                                              qemuBlockStorageSourceAttachDataPtr data)
+{
+    if (data->storageSliceProps) {
+        if (qemuMonitorBlockdevAdd(mon, &data->storageSliceProps) < 0)
+            return -1;
+
+        data->storageSliceAttached = true;
+    }
+
+    return 0;
+}
+
+
 /**
  * qemuBlockStorageSourceAttachApply:
  * @mon: monitor object
@@ -1600,6 +1654,7 @@ qemuBlockStorageSourceAttachApply(qemuMonitorPtr mon,
 {
     if (qemuBlockStorageSourceAttachApplyStorageDeps(mon, data) < 0 ||
         qemuBlockStorageSourceAttachApplyStorage(mon, data) < 0 ||
+        qemuBlockStorageSourceAttachApplyStorageSlice(mon, data) < 0 ||
         qemuBlockStorageSourceAttachApplyFormatDeps(mon, data) < 0 ||
         qemuBlockStorageSourceAttachApplyFormat(mon, data) < 0)
         return -1;
@@ -1642,6 +1697,9 @@ qemuBlockStorageSourceAttachRollback(qemuMonitorPtr mon,
     if (data->formatAttached)
         ignore_value(qemuMonitorBlockdevDel(mon, data->formatNodeName));
 
+    if (data->storageSliceAttached)
+        ignore_value(qemuMonitorBlockdevDel(mon, data->storageSliceNodeName));
+
     if (data->storageAttached)
         ignore_value(qemuMonitorBlockdevDel(mon, data->storageNodeName));
 
@@ -1689,6 +1747,14 @@ qemuBlockStorageSourceDetachPrepare(virStorageSourcePtr src,
         data->formatAttached = true;
         data->storageNodeName = src->nodestorage;
         data->storageAttached = true;
+
+        /* 'raw' format doesn't need the extra 'raw' layer when slicing, thus
+         * the nodename is NULL */
+        if (src->sliceStorage &&
+            src->sliceStorage->nodename) {
+            data->storageSliceNodeName = src->sliceStorage->nodename;
+            data->storageSliceAttached = true;
+        }
     }
 
     if (src->pr &&
index a816190bb78446128ff5f8dbe942b6e51167595f..eab0128d5d92f1d95fbf0fbef77d2049b0c357c1 100644 (file)
@@ -82,6 +82,10 @@ struct qemuBlockStorageSourceAttachData {
     const char *storageNodeName;
     bool storageAttached;
 
+    virJSONValuePtr storageSliceProps;
+    const char *storageSliceNodeName;
+    bool storageSliceAttached;
+
     virJSONValuePtr formatProps;
     const char *formatNodeName;
     bool formatAttached;
index 6b59bbeb2c0c098aee55c821b70a2854672ba80f..71df0d1ab2830f78b88bd37e954d96472b41413a 100644 (file)
@@ -1316,6 +1316,7 @@ qemuBlockJobProcessEventConcludedCreate(virQEMUDriverPtr driver,
     backend->formatAttached = false;
     if (job->data.create.storage) {
         backend->storageAttached = false;
+        backend->storageSliceAttached = false;
         VIR_FREE(backend->encryptsecretAlias);
     }
 
index 60f8820c648d2d7e2d6331c2e53f784620f9b801..f69a9e651c08bc75875e77769415d4818b94dccc 100644 (file)
@@ -2411,6 +2411,14 @@ qemuBuildBlockStorageSourceAttachDataCommandline(virCommandPtr cmd,
         VIR_FREE(tmp);
     }
 
+    if (data->storageSliceProps) {
+        if (!(tmp = virJSONValueToString(data->storageSliceProps, false)))
+            return -1;
+
+        virCommandAddArgList(cmd, "-blockdev", tmp, NULL);
+        VIR_FREE(tmp);
+    }
+
     if (data->formatProps) {
         if (!(tmp = virJSONValueToString(data->formatProps, false)))
             return -1;
index 1c4f76f047c04875d365946a7b59dfe8ea5e31fc..af6817cc0526895759b8a4b14db778bddeae6961 100644 (file)
@@ -16264,6 +16264,10 @@ qemuDomainPrepareStorageSourceBlockdev(virDomainDiskDefPtr disk,
     src->nodestorage = g_strdup_printf("libvirt-%u-storage", src->id);
     src->nodeformat = g_strdup_printf("libvirt-%u-format", src->id);
 
+    if (src->sliceStorage &&
+        src->format != VIR_STORAGE_FILE_RAW)
+        src->sliceStorage->nodename = g_strdup_printf("libvirt-%u-slice-sto", src->id);
+
     if (qemuDomainValidateStorageSource(src, priv->qemuCaps) < 0)
         return -1;