render / rpms / libvirt

Forked from rpms/libvirt 10 months ago
Clone
a1c947
From 5853ac5261b2934ca300b24a7bd78cc4b377c90c Mon Sep 17 00:00:00 2001
a1c947
Message-Id: <5853ac5261b2934ca300b24a7bd78cc4b377c90c@dist-git>
a1c947
From: Michal Privoznik <mprivozn@redhat.com>
a1c947
Date: Thu, 7 Jul 2022 17:37:46 +0200
a1c947
Subject: [PATCH] qemu: Make IOThread changing more robust
a1c947
MIME-Version: 1.0
a1c947
Content-Type: text/plain; charset=UTF-8
a1c947
Content-Transfer-Encoding: 8bit
a1c947
a1c947
There are three APIs that allow changing IOThreads:
a1c947
a1c947
  virDomainAddIOThread()
a1c947
  virDomainDelIOThread()
a1c947
  virDomainSetIOThreadParams()
a1c947
a1c947
In case of QEMU driver these are handled by
a1c947
qemuDomainChgIOThread() which attempts to be versatile enough to
a1c947
work on both inactive and live domain definitions at the same
a1c947
time. However, it's a bit clumsy - when a change to live
a1c947
definition succeeds but fails in inactive definition then there's
a1c947
no rollback. And somewhat rightfully so - changes to live
a1c947
definition are in general harder to roll back. Therefore, do what
a1c947
we do elsewhere (qemuDomainAttachDeviceLiveAndConfig(),
a1c947
qemuDomainDetachDeviceAliasLiveAndConfig(), ...):
a1c947
a1c947
  1) do the change to inactive XML first,
a1c947
  2) in fact, do the change to a copy of inactive XML,
a1c947
  3) swap inactive XML and its copy only after everything
a1c947
     succeeded.
a1c947
a1c947
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
a1c947
Reviewed-by: Ján Tomko <jtomko@redhat.com>
a1c947
(cherry picked from commit 6db9c95a45d4e24cdcd5c009b7fe5da3745b5d59)
a1c947
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2059511
a1c947
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
a1c947
---
a1c947
 src/qemu/qemu_driver.c | 74 ++++++++++++++++++++++++------------------
a1c947
 1 file changed, 43 insertions(+), 31 deletions(-)
a1c947
a1c947
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
a1c947
index 3b5c3db67c..2c627396f1 100644
a1c947
--- a/src/qemu/qemu_driver.c
a1c947
+++ b/src/qemu/qemu_driver.c
a1c947
@@ -5594,6 +5594,7 @@ qemuDomainChgIOThread(virQEMUDriver *driver,
a1c947
 {
a1c947
     g_autoptr(virQEMUDriverConfig) cfg = NULL;
a1c947
     qemuDomainObjPrivate *priv;
a1c947
+    g_autoptr(virDomainDef) defcopy = NULL;
a1c947
     virDomainDef *def;
a1c947
     virDomainDef *persistentDef;
a1c947
     virDomainIOThreadIDDef *iothreaddef = NULL;
a1c947
@@ -5609,34 +5610,34 @@ qemuDomainChgIOThread(virQEMUDriver *driver,
a1c947
     if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
a1c947
         goto endjob;
a1c947
 
a1c947
-    if (def) {
a1c947
-        if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_IOTHREAD)) {
a1c947
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
a1c947
-                           _("IOThreads not supported with this binary"));
a1c947
-            goto endjob;
a1c947
-        }
a1c947
+    if (persistentDef) {
a1c947
+        /* Make a copy of persistent definition and do all the changes there.
a1c947
+         * Swap the definitions only after changes to live definition
a1c947
+         * succeeded. */
a1c947
+        if (!(defcopy = virDomainObjCopyPersistentDef(vm, driver->xmlopt,
a1c947
+                                                      priv->qemuCaps)))
a1c947
+            return -1;
a1c947
 
a1c947
         switch (action) {
a1c947
         case VIR_DOMAIN_IOTHREAD_ACTION_ADD:
a1c947
-            if (virDomainDriverAddIOThreadCheck(def, iothread.iothread_id) < 0)
a1c947
+            if (virDomainDriverAddIOThreadCheck(defcopy, iothread.iothread_id) < 0)
a1c947
                 goto endjob;
a1c947
 
a1c947
-            if (qemuDomainHotplugAddIOThread(driver, vm, iothread.iothread_id) < 0)
a1c947
+            if (!virDomainIOThreadIDAdd(defcopy, iothread.iothread_id))
a1c947
                 goto endjob;
a1c947
 
a1c947
             break;
a1c947
 
a1c947
         case VIR_DOMAIN_IOTHREAD_ACTION_DEL:
a1c947
-            if (virDomainDriverDelIOThreadCheck(def, iothread.iothread_id) < 0)
a1c947
+            if (virDomainDriverDelIOThreadCheck(defcopy, iothread.iothread_id) < 0)
a1c947
                 goto endjob;
a1c947
 
a1c947
-            if (qemuDomainHotplugDelIOThread(driver, vm, iothread.iothread_id) < 0)
a1c947
-                goto endjob;
a1c947
+            virDomainIOThreadIDDel(defcopy, iothread.iothread_id);
a1c947
 
a1c947
             break;
a1c947
 
a1c947
         case VIR_DOMAIN_IOTHREAD_ACTION_MOD:
a1c947
-            iothreaddef = virDomainIOThreadIDFind(def, iothread.iothread_id);
a1c947
+            iothreaddef = virDomainIOThreadIDFind(defcopy, iothread.iothread_id);
a1c947
 
a1c947
             if (!iothreaddef) {
a1c947
                 virReportError(VIR_ERR_INVALID_ARG,
a1c947
@@ -5645,41 +5646,47 @@ qemuDomainChgIOThread(virQEMUDriver *driver,
a1c947
                 goto endjob;
a1c947
             }
a1c947
 
a1c947
-            if (qemuDomainIOThreadValidate(iothreaddef, iothread, true) < 0)
a1c947
+            if (qemuDomainIOThreadValidate(iothreaddef, iothread, false) < 0)
a1c947
                 goto endjob;
a1c947
 
a1c947
-            if (qemuDomainHotplugModIOThread(driver, vm, iothread) < 0)
a1c947
+            if (qemuDomainHotplugModIOThreadIDDef(iothreaddef, iothread) < 0) {
a1c947
+                virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
a1c947
+                               _("configuring persistent polling values is not supported"));
a1c947
                 goto endjob;
a1c947
+            }
a1c947
 
a1c947
-            qemuDomainHotplugModIOThreadIDDef(iothreaddef, iothread);
a1c947
             break;
a1c947
-
a1c947
         }
a1c947
-
a1c947
-        qemuDomainSaveStatus(vm);
a1c947
     }
a1c947
 
a1c947
-    if (persistentDef) {
a1c947
+    if (def) {
a1c947
+        if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_IOTHREAD)) {
a1c947
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
a1c947
+                           _("IOThreads not supported with this binary"));
a1c947
+            goto endjob;
a1c947
+        }
a1c947
+
a1c947
         switch (action) {
a1c947
         case VIR_DOMAIN_IOTHREAD_ACTION_ADD:
a1c947
-            if (virDomainDriverAddIOThreadCheck(persistentDef, iothread.iothread_id) < 0)
a1c947
+            if (virDomainDriverAddIOThreadCheck(def, iothread.iothread_id) < 0)
a1c947
                 goto endjob;
a1c947
 
a1c947
-            if (!virDomainIOThreadIDAdd(persistentDef, iothread.iothread_id))
a1c947
+            if (qemuDomainHotplugAddIOThread(driver, vm, iothread.iothread_id) < 0)
a1c947
                 goto endjob;
a1c947
 
a1c947
             break;
a1c947
 
a1c947
         case VIR_DOMAIN_IOTHREAD_ACTION_DEL:
a1c947
-            if (virDomainDriverDelIOThreadCheck(persistentDef, iothread.iothread_id) < 0)
a1c947
+            if (virDomainDriverDelIOThreadCheck(def, iothread.iothread_id) < 0)
a1c947
                 goto endjob;
a1c947
 
a1c947
-            virDomainIOThreadIDDel(persistentDef, iothread.iothread_id);
a1c947
+            if (qemuDomainHotplugDelIOThread(driver, vm, iothread.iothread_id) < 0)
a1c947
+                goto endjob;
a1c947
 
a1c947
             break;
a1c947
 
a1c947
         case VIR_DOMAIN_IOTHREAD_ACTION_MOD:
a1c947
-            iothreaddef = virDomainIOThreadIDFind(persistentDef, iothread.iothread_id);
a1c947
+            iothreaddef = virDomainIOThreadIDFind(def, iothread.iothread_id);
a1c947
 
a1c947
             if (!iothreaddef) {
a1c947
                 virReportError(VIR_ERR_INVALID_ARG,
a1c947
@@ -5688,21 +5695,26 @@ qemuDomainChgIOThread(virQEMUDriver *driver,
a1c947
                 goto endjob;
a1c947
             }
a1c947
 
a1c947
-            if (qemuDomainIOThreadValidate(iothreaddef, iothread, false) < 0)
a1c947
+            if (qemuDomainIOThreadValidate(iothreaddef, iothread, true) < 0)
a1c947
                 goto endjob;
a1c947
 
a1c947
-            if (qemuDomainHotplugModIOThreadIDDef(iothreaddef, iothread) < 0) {
a1c947
-                virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
a1c947
-                               _("configuring persistent polling values is not supported"));
a1c947
+            if (qemuDomainHotplugModIOThread(driver, vm, iothread) < 0)
a1c947
                 goto endjob;
a1c947
-            }
a1c947
 
a1c947
+            qemuDomainHotplugModIOThreadIDDef(iothreaddef, iothread);
a1c947
             break;
a1c947
+
a1c947
         }
a1c947
 
a1c947
-        if (virDomainDefSave(persistentDef, driver->xmlopt,
a1c947
-                             cfg->configDir) < 0)
a1c947
+        qemuDomainSaveStatus(vm);
a1c947
+    }
a1c947
+
a1c947
+    /* Finally, if no error until here, we can save config. */
a1c947
+    if (defcopy) {
a1c947
+        if (virDomainDefSave(defcopy, driver->xmlopt, cfg->configDir) < 0)
a1c947
             goto endjob;
a1c947
+
a1c947
+        virDomainObjAssignDef(vm, &defcopy, false, NULL);
a1c947
     }
a1c947
 
a1c947
     ret = 0;
a1c947
-- 
a1c947
2.35.1
a1c947