0b8103
From 8eaad4cc89e78c25ccca3481741cded0538046b0 Mon Sep 17 00:00:00 2001
0b8103
Message-Id: <8eaad4cc89e78c25ccca3481741cded0538046b0@dist-git>
0b8103
From: Peter Krempa <pkrempa@redhat.com>
0b8103
Date: Wed, 28 Jul 2021 17:37:21 +0200
0b8103
Subject: [PATCH] RHEL: Enable usage of x-blockdev-reopen
0b8103
MIME-Version: 1.0
0b8103
Content-Type: text/plain; charset=UTF-8
0b8103
Content-Transfer-Encoding: 8bit
0b8103
0b8103
RHEL-only
0b8103
0b8103
Introduce a new capability QEMU_CAPS_BLOCKDEV_REOPEN_COM_REDHAT_AV_8_2_0_API
0b8103
based on the presence of '__com.redhat_rhel-av-8_2_0-api' feature for
0b8103
'x-blockdev-reopen' which states that reopen works for what libvirt
0b8103
is going to use it and wire up code to call the x- prefixed command.
0b8103
0b8103
This implementation will become dormant once qemu starts supporting
0b8103
upstream-stable blockdev-reopen.
0b8103
0b8103
https://bugzilla.redhat.com/show_bug.cgi?id=1799013
0b8103
0b8103
Starting with libvirt-7.6, upstream has adapted to the new format of
0b8103
arguments so this patch was modified to support blockdev-reopen which
0b8103
takes an array of nodes to reopen.
0b8103
0b8103
https://bugzilla.redhat.com/show_bug.cgi?id=1929765
0b8103
Message-Id: <3fcde2fc6add36d5276ae224caf18adc8bca7d48.1627486352.git.pkrempa@redhat.com>
0b8103
Reviewed-by: Ján Tomko <jtomko@redhat.com>
0b8103
---
0b8103
 src/qemu/qemu_block.c        | 24 +++++++++++++++---------
0b8103
 src/qemu/qemu_block.h        |  3 ++-
0b8103
 src/qemu/qemu_capabilities.c | 11 +++++++++++
0b8103
 src/qemu/qemu_capabilities.h |  1 +
0b8103
 src/qemu/qemu_monitor.c      |  5 +++--
0b8103
 src/qemu/qemu_monitor.h      |  3 ++-
0b8103
 src/qemu/qemu_monitor_json.c | 12 +++++++++---
0b8103
 src/qemu/qemu_monitor_json.h |  3 ++-
0b8103
 tests/qemumonitorjsontest.c  |  2 +-
0b8103
 9 files changed, 46 insertions(+), 18 deletions(-)
0b8103
0b8103
diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
0b8103
index 4691dff4f7..1f731fff3d 100644
0b8103
--- a/src/qemu/qemu_block.c
0b8103
+++ b/src/qemu/qemu_block.c
0b8103
@@ -3289,7 +3289,8 @@ qemuBlockBitmapsHandleCommitFinish(virStorageSource *topsrc,
0b8103
 
0b8103
 int
0b8103
 qemuBlockReopenFormatMon(qemuMonitor *mon,
0b8103
-                         virStorageSource *src)
0b8103
+                         virStorageSource *src,
0b8103
+                         bool downstream)
0b8103
 {
0b8103
     g_autoptr(virJSONValue) reopenprops = NULL;
0b8103
     g_autoptr(virJSONValue) srcprops = NULL;
0b8103
@@ -3298,15 +3299,19 @@ qemuBlockReopenFormatMon(qemuMonitor *mon,
0b8103
     if (!(srcprops = qemuBlockStorageSourceGetBlockdevProps(src, src->backingStore)))
0b8103
         return -1;
0b8103
 
0b8103
-    if (virJSONValueArrayAppend(reopenoptions, &srcprops) < 0)
0b8103
-        return -1;
0b8103
+    if (downstream) {
0b8103
+        reopenprops = g_steal_pointer(&srcprops);
0b8103
+    } else {
0b8103
+        if (virJSONValueArrayAppend(reopenoptions, &srcprops) < 0)
0b8103
+            return -1;
0b8103
 
0b8103
-    if (virJSONValueObjectCreate(&reopenprops,
0b8103
-                                 "a:options", &reopenoptions,
0b8103
-                                 NULL) < 0)
0b8103
-        return -1;
0b8103
+        if (virJSONValueObjectCreate(&reopenprops,
0b8103
+                                     "a:options", &reopenoptions,
0b8103
+                                     NULL) < 0)
0b8103
+            return -1;
0b8103
+    }
0b8103
 
0b8103
-    if (qemuMonitorBlockdevReopen(mon, &reopenprops) < 0)
0b8103
+    if (qemuMonitorBlockdevReopen(mon, &reopenprops, downstream) < 0)
0b8103
         return -1;
0b8103
 
0b8103
     return 0;
0b8103
@@ -3330,6 +3335,7 @@ qemuBlockReopenFormat(virDomainObj *vm,
0b8103
 {
0b8103
     qemuDomainObjPrivate *priv = vm->privateData;
0b8103
     virQEMUDriver *driver = priv->driver;
0b8103
+    bool downstream = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV_REOPEN_COM_REDHAT_AV_8_2_0_API);
0b8103
     int rc;
0b8103
 
0b8103
     /* If we are lacking the object here, qemu might have opened an image with
0b8103
@@ -3343,7 +3349,7 @@ qemuBlockReopenFormat(virDomainObj *vm,
0b8103
     if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
0b8103
         return -1;
0b8103
 
0b8103
-    rc = qemuBlockReopenFormatMon(priv->mon, src);
0b8103
+    rc = qemuBlockReopenFormatMon(priv->mon, src, downstream);
0b8103
 
0b8103
     if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
0b8103
         return -1;
0b8103
diff --git a/src/qemu/qemu_block.h b/src/qemu/qemu_block.h
0b8103
index 54601a48a9..88fc9974c4 100644
0b8103
--- a/src/qemu/qemu_block.h
0b8103
+++ b/src/qemu/qemu_block.h
0b8103
@@ -268,7 +268,8 @@ qemuBlockBitmapsHandleCommitFinish(virStorageSource *topsrc,
0b8103
 /* only for use in qemumonitorjsontest */
0b8103
 int
0b8103
 qemuBlockReopenFormatMon(qemuMonitor *mon,
0b8103
-                         virStorageSource *src);
0b8103
+                         virStorageSource *src,
0b8103
+                         bool downstream);
0b8103
 
0b8103
 int
0b8103
 qemuBlockReopenReadWrite(virDomainObj *vm,
0b8103
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
0b8103
index 9558938866..6734ed213d 100644
0b8103
--- a/src/qemu/qemu_capabilities.c
0b8103
+++ b/src/qemu/qemu_capabilities.c
0b8103
@@ -637,6 +637,7 @@ VIR_ENUM_IMPL(virQEMUCaps,
0b8103
               "confidential-guest-support",
0b8103
               "query-display-options",
0b8103
               "s390-pv-guest",
0b8103
+              "blockdev-reopen.__com.redhat_rhel-av-8_2_0-api",
0b8103
     );
0b8103
 
0b8103
 
0b8103
@@ -1551,6 +1552,7 @@ static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsVhostUserFS[] =
0b8103
 
0b8103
 /* see documentation for virQEMUQAPISchemaPathGet for the query format */
0b8103
 static struct virQEMUCapsStringFlags virQEMUCapsQMPSchemaQueries[] = {
0b8103
+    { "x-blockdev-reopen/$__com.redhat_rhel-av-8_2_0-api", QEMU_CAPS_BLOCKDEV_REOPEN_COM_REDHAT_AV_8_2_0_API },
0b8103
     { "blockdev-add/arg-type/options/+gluster/debug-level", QEMU_CAPS_GLUSTER_DEBUG_LEVEL},
0b8103
     { "blockdev-add/arg-type/+gluster/debug", QEMU_CAPS_GLUSTER_DEBUG_LEVEL},
0b8103
     { "blockdev-add/arg-type/+vxhs", QEMU_CAPS_VXHS},
0b8103
@@ -5204,6 +5206,15 @@ virQEMUCapsInitProcessCaps(virQEMUCaps *qemuCaps)
0b8103
         qemuCaps->arch == VIR_ARCH_MIPS)
0b8103
         virQEMUCapsSet(qemuCaps, QEMU_CAPS_SCSI_NCR53C90);
0b8103
 
0b8103
+    /* RHEL-only:
0b8103
+     * - if upstream blockdev-reopen is enabled, clear the downstream flag
0b8103
+     * - if the downstream flag is present but not the upstream, assert the upstream flag too
0b8103
+     */
0b8103
+    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_BLOCKDEV_REOPEN))
0b8103
+        virQEMUCapsClear(qemuCaps, QEMU_CAPS_BLOCKDEV_REOPEN_COM_REDHAT_AV_8_2_0_API);
0b8103
+    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_BLOCKDEV_REOPEN_COM_REDHAT_AV_8_2_0_API))
0b8103
+        virQEMUCapsSet(qemuCaps, QEMU_CAPS_BLOCKDEV_REOPEN);
0b8103
+
0b8103
     virQEMUCapsInitProcessCapsInterlock(qemuCaps);
0b8103
 }
0b8103
 
0b8103
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
0b8103
index 2b1bb57a49..def0dd2030 100644
0b8103
--- a/src/qemu/qemu_capabilities.h
0b8103
+++ b/src/qemu/qemu_capabilities.h
0b8103
@@ -617,6 +617,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */
0b8103
     QEMU_CAPS_MACHINE_CONFIDENTAL_GUEST_SUPPORT, /* -machine confidential-guest-support */
0b8103
     QEMU_CAPS_QUERY_DISPLAY_OPTIONS, /* 'query-display-options' qmp command present */
0b8103
     QEMU_CAPS_S390_PV_GUEST, /* -object s390-pv-guest,... */
0b8103
+    QEMU_CAPS_BLOCKDEV_REOPEN_COM_REDHAT_AV_8_2_0_API, /* downstream support for blockdev reopen in rhel-av-8.2.0 */
0b8103
 
0b8103
     QEMU_CAPS_LAST /* this must always be the last item */
0b8103
 } virQEMUCapsFlags;
0b8103
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
0b8103
index 6e2d8010c5..7ebaa7b099 100644
0b8103
--- a/src/qemu/qemu_monitor.c
0b8103
+++ b/src/qemu/qemu_monitor.c
0b8103
@@ -4339,14 +4339,15 @@ qemuMonitorBlockdevAdd(qemuMonitor *mon,
0b8103
 
0b8103
 int
0b8103
 qemuMonitorBlockdevReopen(qemuMonitor *mon,
0b8103
-                          virJSONValue **props)
0b8103
+                          virJSONValue **props,
0b8103
+                          bool downstream)
0b8103
 {
0b8103
     VIR_DEBUG("props=%p (node-name=%s)", *props,
0b8103
               NULLSTR(virJSONValueObjectGetString(*props, "node-name")));
0b8103
 
0b8103
     QEMU_CHECK_MONITOR(mon);
0b8103
 
0b8103
-    return qemuMonitorJSONBlockdevReopen(mon, props);
0b8103
+    return qemuMonitorJSONBlockdevReopen(mon, props, downstream);
0b8103
 }
0b8103
 
0b8103
 
0b8103
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
0b8103
index 1491c1297c..5a93447e23 100644
0b8103
--- a/src/qemu/qemu_monitor.h
0b8103
+++ b/src/qemu/qemu_monitor.h
0b8103
@@ -1366,7 +1366,8 @@ int qemuMonitorBlockdevAdd(qemuMonitor *mon,
0b8103
                            virJSONValue **props);
0b8103
 
0b8103
 int qemuMonitorBlockdevReopen(qemuMonitor *mon,
0b8103
-                              virJSONValue **props);
0b8103
+                              virJSONValue **props,
0b8103
+                              bool downstream);
0b8103
 
0b8103
 int qemuMonitorBlockdevDel(qemuMonitor *mon,
0b8103
                            const char *nodename);
0b8103
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
0b8103
index ca2c3bb6cf..8ecd5f3bbd 100644
0b8103
--- a/src/qemu/qemu_monitor_json.c
0b8103
+++ b/src/qemu/qemu_monitor_json.c
0b8103
@@ -8687,13 +8687,19 @@ qemuMonitorJSONBlockdevAdd(qemuMonitor *mon,
0b8103
 
0b8103
 int
0b8103
 qemuMonitorJSONBlockdevReopen(qemuMonitor *mon,
0b8103
-                              virJSONValue **props)
0b8103
+                              virJSONValue **props,
0b8103
+                              bool downstream)
0b8103
 {
0b8103
     g_autoptr(virJSONValue) cmd = NULL;
0b8103
     g_autoptr(virJSONValue) reply = NULL;
0b8103
 
0b8103
-    if (!(cmd = qemuMonitorJSONMakeCommandInternal("blockdev-reopen", props)))
0b8103
-        return -1;
0b8103
+    if (downstream) {
0b8103
+        if (!(cmd = qemuMonitorJSONMakeCommandInternal("x-blockdev-reopen", props)))
0b8103
+            return -1;
0b8103
+    } else {
0b8103
+        if (!(cmd = qemuMonitorJSONMakeCommandInternal("blockdev-reopen", props)))
0b8103
+            return -1;
0b8103
+    }
0b8103
 
0b8103
     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
0b8103
         return -1;
0b8103
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
0b8103
index 01a3ba25f1..90792c9939 100644
0b8103
--- a/src/qemu/qemu_monitor_json.h
0b8103
+++ b/src/qemu/qemu_monitor_json.h
0b8103
@@ -601,7 +601,8 @@ int qemuMonitorJSONBlockdevAdd(qemuMonitor *mon,
0b8103
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
0b8103
 
0b8103
 int qemuMonitorJSONBlockdevReopen(qemuMonitor *mon,
0b8103
-                                  virJSONValue **props)
0b8103
+                                  virJSONValue **props,
0b8103
+                                  bool downstream)
0b8103
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
0b8103
 
0b8103
 int qemuMonitorJSONBlockdevDel(qemuMonitor *mon,
0b8103
diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c
0b8103
index 2122d9d999..c20287afee 100644
0b8103
--- a/tests/qemumonitorjsontest.c
0b8103
+++ b/tests/qemumonitorjsontest.c
0b8103
@@ -2820,7 +2820,7 @@ testQemuMonitorJSONBlockdevReopen(const void *opaque)
0b8103
     if (qemuMonitorTestAddItem(test, "blockdev-reopen", "{\"return\":{}}") < 0)
0b8103
         return -1;
0b8103
 
0b8103
-    if (qemuBlockReopenFormatMon(qemuMonitorTestGetMonitor(test), src) < 0)
0b8103
+    if (qemuBlockReopenFormatMon(qemuMonitorTestGetMonitor(test), src, false) < 0)
0b8103
         return -1;
0b8103
 
0b8103
     return 0;
0b8103
-- 
0b8103
2.32.0
0b8103