d76c62
From 9d2cbc9ca4405fcf11e5796414af0038eb7c7f9e Mon Sep 17 00:00:00 2001
d76c62
Message-Id: <9d2cbc9ca4405fcf11e5796414af0038eb7c7f9e@dist-git>
d76c62
From: Peter Krempa <pkrempa@redhat.com>
d76c62
Date: Wed, 19 Feb 2020 15:10:24 +0100
d76c62
Subject: [PATCH] qemu: Add support for slices of type 'storage'
d76c62
MIME-Version: 1.0
d76c62
Content-Type: text/plain; charset=UTF-8
d76c62
Content-Transfer-Encoding: 8bit
d76c62
d76c62
Implement support for the slice of type 'storage' which allows to set
d76c62
the offset and size which modifies where qemu should look for the start
d76c62
of the format container inside the image.
d76c62
d76c62
Since slicing is done using the 'raw' driver we need to add another
d76c62
layer into the blockdev tree if there's any non-raw image format driver
d76c62
used to access the data.
d76c62
d76c62
This patch adds the blockdev integration and setup of the image data so
d76c62
that we can use the slices for any backing image.
d76c62
d76c62
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
d76c62
Reviewed-by: Ján Tomko <jtomko@redhat.com>
d76c62
(cherry picked from commit 0e644e6e47a48830dc10b090a999d4ba2e7d5394)
d76c62
d76c62
https://bugzilla.redhat.com/show_bug.cgi?id=1791788
d76c62
Message-Id: <1f8e63abfd1836f1df91f54cf2c018a7d5047825.1582120424.git.pkrempa@redhat.com>
d76c62
Reviewed-by: Ján Tomko <jtomko@redhat.com>
d76c62
---
d76c62
 src/qemu/qemu_block.c    | 68 +++++++++++++++++++++++++++++++++++++++-
d76c62
 src/qemu/qemu_block.h    |  4 +++
d76c62
 src/qemu/qemu_blockjob.c |  1 +
d76c62
 src/qemu/qemu_command.c  |  8 +++++
d76c62
 src/qemu/qemu_domain.c   |  4 +++
d76c62
 5 files changed, 84 insertions(+), 1 deletion(-)
d76c62
d76c62
diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
d76c62
index 387a2db2e6..5bd5c955a4 100644
d76c62
--- a/src/qemu/qemu_block.c
d76c62
+++ b/src/qemu/qemu_block.c
d76c62
@@ -1423,11 +1423,16 @@ qemuBlockStorageSourceGetBlockdevProps(virStorageSourcePtr src,
d76c62
                                        virStorageSourcePtr backingStore)
d76c62
 {
d76c62
     g_autoptr(virJSONValue) props = NULL;
d76c62
+    const char *storagenode = src->nodestorage;
d76c62
+
d76c62
+    if (src->sliceStorage &&
d76c62
+        src->format != VIR_STORAGE_FILE_RAW)
d76c62
+        storagenode = src->sliceStorage->nodename;
d76c62
 
d76c62
     if (!(props = qemuBlockStorageSourceGetBlockdevFormatProps(src)))
d76c62
         return NULL;
d76c62
 
d76c62
-    if (virJSONValueObjectAppendString(props, "file", src->nodestorage) < 0)
d76c62
+    if (virJSONValueObjectAppendString(props, "file", storagenode) < 0)
d76c62
         return NULL;
d76c62
 
d76c62
     if (backingStore) {
d76c62
@@ -1456,6 +1461,32 @@ qemuBlockStorageSourceGetBlockdevProps(virStorageSourcePtr src,
d76c62
 }
d76c62
 
d76c62
 
d76c62
+static virJSONValuePtr
d76c62
+qemuBlockStorageSourceGetBlockdevStorageSliceProps(virStorageSourcePtr src)
d76c62
+{
d76c62
+    g_autoptr(virJSONValue) props = NULL;
d76c62
+
d76c62
+    if (qemuBlockNodeNameValidate(src->sliceStorage->nodename) < 0)
d76c62
+        return NULL;
d76c62
+
d76c62
+    if (virJSONValueObjectCreate(&props,
d76c62
+                                 "s:driver", "raw",
d76c62
+                                 "s:node-name", src->sliceStorage->nodename,
d76c62
+                                 "U:offset", src->sliceStorage->offset,
d76c62
+                                 "U:size", src->sliceStorage->size,
d76c62
+                                 "s:file", src->nodestorage,
d76c62
+                                 "b:auto-read-only", true,
d76c62
+                                 "s:discard", "unmap",
d76c62
+                                 NULL) < 0)
d76c62
+        return NULL;
d76c62
+
d76c62
+    if (qemuBlockStorageSourceGetBlockdevGetCacheProps(src, props) < 0)
d76c62
+        return NULL;
d76c62
+
d76c62
+    return g_steal_pointer(&props;;
d76c62
+}
d76c62
+
d76c62
+
d76c62
 void
d76c62
 qemuBlockStorageSourceAttachDataFree(qemuBlockStorageSourceAttachDataPtr data)
d76c62
 {
d76c62
@@ -1463,6 +1494,7 @@ qemuBlockStorageSourceAttachDataFree(qemuBlockStorageSourceAttachDataPtr data)
d76c62
         return;
d76c62
 
d76c62
     virJSONValueFree(data->storageProps);
d76c62
+    virJSONValueFree(data->storageSliceProps);
d76c62
     virJSONValueFree(data->formatProps);
d76c62
     virJSONValueFree(data->prmgrProps);
d76c62
     virJSONValueFree(data->authsecretProps);
d76c62
@@ -1513,6 +1545,13 @@ qemuBlockStorageSourceAttachPrepareBlockdev(virStorageSourcePtr src,
d76c62
     data->storageNodeName = src->nodestorage;
d76c62
     data->formatNodeName = src->nodeformat;
d76c62
 
d76c62
+    if (src->sliceStorage && src->format != VIR_STORAGE_FILE_RAW) {
d76c62
+        if (!(data->storageSliceProps = qemuBlockStorageSourceGetBlockdevStorageSliceProps(src)))
d76c62
+            return NULL;
d76c62
+
d76c62
+        data->storageSliceNodeName = src->sliceStorage->nodename;
d76c62
+    }
d76c62
+
d76c62
     return g_steal_pointer(&data);
d76c62
 }
d76c62
 
d76c62
@@ -1581,6 +1620,21 @@ qemuBlockStorageSourceAttachApplyFormat(qemuMonitorPtr mon,
d76c62
 }
d76c62
 
d76c62
 
d76c62
+static int
d76c62
+qemuBlockStorageSourceAttachApplyStorageSlice(qemuMonitorPtr mon,
d76c62
+                                              qemuBlockStorageSourceAttachDataPtr data)
d76c62
+{
d76c62
+    if (data->storageSliceProps) {
d76c62
+        if (qemuMonitorBlockdevAdd(mon, &data->storageSliceProps) < 0)
d76c62
+            return -1;
d76c62
+
d76c62
+        data->storageSliceAttached = true;
d76c62
+    }
d76c62
+
d76c62
+    return 0;
d76c62
+}
d76c62
+
d76c62
+
d76c62
 /**
d76c62
  * qemuBlockStorageSourceAttachApply:
d76c62
  * @mon: monitor object
d76c62
@@ -1600,6 +1654,7 @@ qemuBlockStorageSourceAttachApply(qemuMonitorPtr mon,
d76c62
 {
d76c62
     if (qemuBlockStorageSourceAttachApplyStorageDeps(mon, data) < 0 ||
d76c62
         qemuBlockStorageSourceAttachApplyStorage(mon, data) < 0 ||
d76c62
+        qemuBlockStorageSourceAttachApplyStorageSlice(mon, data) < 0 ||
d76c62
         qemuBlockStorageSourceAttachApplyFormatDeps(mon, data) < 0 ||
d76c62
         qemuBlockStorageSourceAttachApplyFormat(mon, data) < 0)
d76c62
         return -1;
d76c62
@@ -1642,6 +1697,9 @@ qemuBlockStorageSourceAttachRollback(qemuMonitorPtr mon,
d76c62
     if (data->formatAttached)
d76c62
         ignore_value(qemuMonitorBlockdevDel(mon, data->formatNodeName));
d76c62
 
d76c62
+    if (data->storageSliceAttached)
d76c62
+        ignore_value(qemuMonitorBlockdevDel(mon, data->storageSliceNodeName));
d76c62
+
d76c62
     if (data->storageAttached)
d76c62
         ignore_value(qemuMonitorBlockdevDel(mon, data->storageNodeName));
d76c62
 
d76c62
@@ -1689,6 +1747,14 @@ qemuBlockStorageSourceDetachPrepare(virStorageSourcePtr src,
d76c62
         data->formatAttached = true;
d76c62
         data->storageNodeName = src->nodestorage;
d76c62
         data->storageAttached = true;
d76c62
+
d76c62
+        /* 'raw' format doesn't need the extra 'raw' layer when slicing, thus
d76c62
+         * the nodename is NULL */
d76c62
+        if (src->sliceStorage &&
d76c62
+            src->sliceStorage->nodename) {
d76c62
+            data->storageSliceNodeName = src->sliceStorage->nodename;
d76c62
+            data->storageSliceAttached = true;
d76c62
+        }
d76c62
     }
d76c62
 
d76c62
     if (src->pr &&
d76c62
diff --git a/src/qemu/qemu_block.h b/src/qemu/qemu_block.h
d76c62
index a816190bb7..eab0128d5d 100644
d76c62
--- a/src/qemu/qemu_block.h
d76c62
+++ b/src/qemu/qemu_block.h
d76c62
@@ -82,6 +82,10 @@ struct qemuBlockStorageSourceAttachData {
d76c62
     const char *storageNodeName;
d76c62
     bool storageAttached;
d76c62
 
d76c62
+    virJSONValuePtr storageSliceProps;
d76c62
+    const char *storageSliceNodeName;
d76c62
+    bool storageSliceAttached;
d76c62
+
d76c62
     virJSONValuePtr formatProps;
d76c62
     const char *formatNodeName;
d76c62
     bool formatAttached;
d76c62
diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c
d76c62
index 6b59bbeb2c..71df0d1ab2 100644
d76c62
--- a/src/qemu/qemu_blockjob.c
d76c62
+++ b/src/qemu/qemu_blockjob.c
d76c62
@@ -1316,6 +1316,7 @@ qemuBlockJobProcessEventConcludedCreate(virQEMUDriverPtr driver,
d76c62
     backend->formatAttached = false;
d76c62
     if (job->data.create.storage) {
d76c62
         backend->storageAttached = false;
d76c62
+        backend->storageSliceAttached = false;
d76c62
         VIR_FREE(backend->encryptsecretAlias);
d76c62
     }
d76c62
 
d76c62
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
d76c62
index 1a5142d472..252809a8d7 100644
d76c62
--- a/src/qemu/qemu_command.c
d76c62
+++ b/src/qemu/qemu_command.c
d76c62
@@ -2427,6 +2427,14 @@ qemuBuildBlockStorageSourceAttachDataCommandline(virCommandPtr cmd,
d76c62
         VIR_FREE(tmp);
d76c62
     }
d76c62
 
d76c62
+    if (data->storageSliceProps) {
d76c62
+        if (!(tmp = virJSONValueToString(data->storageSliceProps, false)))
d76c62
+            return -1;
d76c62
+
d76c62
+        virCommandAddArgList(cmd, "-blockdev", tmp, NULL);
d76c62
+        VIR_FREE(tmp);
d76c62
+    }
d76c62
+
d76c62
     if (data->formatProps) {
d76c62
         if (!(tmp = virJSONValueToString(data->formatProps, false)))
d76c62
             return -1;
d76c62
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
d76c62
index 948bf3011c..0baa80582c 100644
d76c62
--- a/src/qemu/qemu_domain.c
d76c62
+++ b/src/qemu/qemu_domain.c
d76c62
@@ -16444,6 +16444,10 @@ qemuDomainPrepareStorageSourceBlockdev(virDomainDiskDefPtr disk,
d76c62
     src->nodestorage = g_strdup_printf("libvirt-%u-storage", src->id);
d76c62
     src->nodeformat = g_strdup_printf("libvirt-%u-format", src->id);
d76c62
 
d76c62
+    if (src->sliceStorage &&
d76c62
+        src->format != VIR_STORAGE_FILE_RAW)
d76c62
+        src->sliceStorage->nodename = g_strdup_printf("libvirt-%u-slice-sto", src->id);
d76c62
+
d76c62
     if (qemuDomainValidateStorageSource(src, priv->qemuCaps) < 0)
d76c62
         return -1;
d76c62
 
d76c62
-- 
d76c62
2.25.0
d76c62