|
|
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 |
|