Signed-off-by: Pavel Hrdina <phrdina(a)redhat.com>
---
src/conf/domain_conf.c | 26 ++++++++
src/conf/domain_conf.h | 8 +++
src/libvirt_private.syms | 1 +
src/qemu/qemu_driver.c | 150 +++++++++++++++++++++++++++++++++++++++++--
src/qemu/qemu_monitor.c | 19 ++++++
src/qemu/qemu_monitor.h | 3 +
src/qemu/qemu_monitor_json.c | 32 +++++++++
src/qemu/qemu_monitor_json.h | 4 ++
8 files changed, 236 insertions(+), 7 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 64303a6790..cc1be373ca 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -20370,6 +20370,32 @@ virDomainIOThreadIDAdd(virDomainDefPtr def,
void
+virDomainIOThreadIDMod(virDomainIOThreadIDDefPtr old_iothread,
+ virDomainIOThreadIDDefPtr new_iothread)
+{
+ old_iothread->poll_enabled = new_iothread->poll_enabled;
+
+ switch (new_iothread->poll_enabled) {
+ case VIR_TRISTATE_BOOL_YES:
+ old_iothread->poll_max_ns = new_iothread->poll_max_ns;
+ old_iothread->poll_grow = new_iothread->poll_grow;
+ old_iothread->poll_shrink = new_iothread->poll_shrink;
+ break;
+
+ case VIR_TRISTATE_BOOL_ABSENT:
+ case VIR_TRISTATE_BOOL_NO:
+ old_iothread->poll_max_ns = 0;
+ old_iothread->poll_grow = 0;
+ old_iothread->poll_shrink = 0;
+ break;
+
+ case VIR_TRISTATE_BOOL_LAST:
+ break;
+ }
+}
+
+
+void
virDomainIOThreadIDDel(virDomainDefPtr def,
unsigned int iothread_id)
{
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 5f8c745d8a..6f7edb3bfa 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2065,6 +2065,12 @@ struct _virDomainHugePage {
# define VIR_DOMAIN_CPUMASK_LEN 1024
+typedef enum {
+ VIR_DOMAIN_IOTHREAD_ACTION_ADD,
+ VIR_DOMAIN_IOTHREAD_ACTION_DEL,
+ VIR_DOMAIN_IOTHREAD_ACTION_MOD,
+} virDomainIOThreadAction;
+
typedef struct _virDomainIOThreadIDDef virDomainIOThreadIDDef;
typedef virDomainIOThreadIDDef *virDomainIOThreadIDDefPtr;
@@ -2792,6 +2798,8 @@ virDomainIOThreadIDDefPtr virDomainIOThreadIDFind(const virDomainDef
*def,
unsigned int iothread_id);
virDomainIOThreadIDDefPtr virDomainIOThreadIDAdd(virDomainDefPtr def,
virDomainIOThreadIDDef iothread);
+void virDomainIOThreadIDMod(virDomainIOThreadIDDefPtr old_iothread,
+ virDomainIOThreadIDDefPtr new_iothread);
void virDomainIOThreadIDDel(virDomainDefPtr def, unsigned int iothread_id);
unsigned int virDomainDefFormatConvertXMLFlags(unsigned int flags);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 97aee9c0e3..b9f0ac0c9f 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -376,6 +376,7 @@ virDomainIOThreadIDAdd;
virDomainIOThreadIDDefFree;
virDomainIOThreadIDDel;
virDomainIOThreadIDFind;
+virDomainIOThreadIDMod;
virDomainKeyWrapCipherNameTypeFromString;
virDomainKeyWrapCipherNameTypeToString;
virDomainLeaseDefFree;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 96c8b2b8bc..46dc4a5ffb 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -5662,6 +5662,55 @@ qemuDomainHotplugAddIOThread(virQEMUDriverPtr driver,
goto cleanup;
}
+
+static int
+qemuDomainHotplugModIOThread(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ virDomainIOThreadIDDef iothread,
+ virDomainIOThreadIDDefPtr old_iothread)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ qemuMonitorIOThreadInfo iothread_info = {0};
+ int rc;
+
+ iothread_info.iothread_id = old_iothread->iothread_id;
+
+ switch (iothread.poll_enabled) {
+ case VIR_TRISTATE_BOOL_ABSENT:
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("IOThread polling must be specified for "
+ "live update"));
+ return -1;
+
+ case VIR_TRISTATE_BOOL_YES:
+ iothread_info.poll_max_ns = iothread.poll_max_ns;
+ iothread_info.poll_grow = iothread.poll_grow;
+ iothread_info.poll_shrink = iothread.poll_shrink;
+ break;
+
+ case VIR_TRISTATE_BOOL_NO:
+ /* No need to do anything because iothread_info has all members
+ * initialized to 0 which will disable polling. */
+ case VIR_TRISTATE_BOOL_LAST:
+ break;
+ }
+
+ qemuDomainObjEnterMonitor(driver, vm);
+
+ rc = qemuMonitorSetIOThread(priv->mon, &iothread_info);
+
+ if (qemuDomainObjExitMonitor(driver, vm) < 0)
+ return -1;
+
+ if (rc < 0)
+ return -1;
+
+ virDomainIOThreadIDMod(old_iothread, &iothread);
+
+ return 0;
+}
+
+
static int
qemuDomainHotplugDelIOThread(virQEMUDriverPtr driver,
virDomainObjPtr vm,
@@ -5742,6 +5791,21 @@ qemuDomainAddIOThreadCheck(virDomainDefPtr def,
}
+static virDomainIOThreadIDDefPtr
+qemuDomainModIOThreadGet(virDomainDefPtr def,
+ unsigned int iothread_id)
+{
+ virDomainIOThreadIDDefPtr ret = NULL;
+
+ if (!(ret = virDomainIOThreadIDFind(def, iothread_id)))
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("cannot find IOThread '%u' in iothreadids
list"),
+ iothread_id);
+
+ return ret;
+}
+
+
static int
qemuDomainDelIOThreadCheck(virDomainDefPtr def,
unsigned int iothread_id)
@@ -5845,13 +5909,14 @@ static int
qemuDomainChgIOThread(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virDomainIOThreadIDDef iothread,
- bool add,
+ virDomainIOThreadAction action,
unsigned int flags)
{
virQEMUDriverConfigPtr cfg = NULL;
qemuDomainObjPrivatePtr priv;
virDomainDefPtr def;
virDomainDefPtr persistentDef;
+ virDomainIOThreadIDDefPtr old_iothread = NULL;
int ret = -1;
cfg = virQEMUDriverGetConfig(driver);
@@ -5871,19 +5936,34 @@ qemuDomainChgIOThread(virQEMUDriverPtr driver,
goto endjob;
}
- if (add) {
+ switch (action) {
+ case VIR_DOMAIN_IOTHREAD_ACTION_ADD:
if (qemuDomainAddIOThreadCheck(def, iothread.iothread_id) < 0)
goto endjob;
if (qemuDomainHotplugAddIOThread(driver, vm, iothread) < 0)
goto endjob;
- } else {
+ break;
+
+ case VIR_DOMAIN_IOTHREAD_ACTION_DEL:
if (qemuDomainDelIOThreadCheck(def, iothread.iothread_id) < 0)
goto endjob;
if (qemuDomainHotplugDelIOThread(driver, vm,
iothread.iothread_id) < 0)
goto endjob;
+ break;
+
+ case VIR_DOMAIN_IOTHREAD_ACTION_MOD:
+ if (!(old_iothread = qemuDomainModIOThreadGet(def,
+ iothread.iothread_id)))
+ goto endjob;
+
+ if (qemuDomainHotplugModIOThread(driver, vm, iothread,
+ old_iothread) < 0)
+ goto endjob;
+
+ break;
}
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm,
@@ -5892,19 +5972,30 @@ qemuDomainChgIOThread(virQEMUDriverPtr driver,
}
if (persistentDef) {
- if (add) {
+ switch (action) {
+ case VIR_DOMAIN_IOTHREAD_ACTION_ADD:
if (qemuDomainAddIOThreadCheck(persistentDef,
iothread.iothread_id) < 0)
goto endjob;
if (!virDomainIOThreadIDAdd(persistentDef, iothread))
goto endjob;
- } else {
+ break;
+
+ case VIR_DOMAIN_IOTHREAD_ACTION_DEL:
if (qemuDomainDelIOThreadCheck(persistentDef,
iothread.iothread_id) < 0)
goto endjob;
virDomainIOThreadIDDel(persistentDef, iothread.iothread_id);
+
+ case VIR_DOMAIN_IOTHREAD_ACTION_MOD:
+ if (!(old_iothread = qemuDomainModIOThreadGet(persistentDef,
+ iothread.iothread_id)))
+ goto endjob;
+
+ virDomainIOThreadIDMod(old_iothread, &iothread);
+ break;
}
if (virDomainSaveConfig(cfg->configDir, driver->caps,
@@ -5955,7 +6046,8 @@ qemuDomainAddIOThreadParams(virDomainPtr dom,
if (virDomainAddIOThreadParamsEnsureACL(dom->conn, vm->def, flags) < 0)
goto cleanup;
- ret = qemuDomainChgIOThread(driver, vm, iothread, true, flags);
+ ret = qemuDomainChgIOThread(driver, vm, iothread,
+ VIR_DOMAIN_IOTHREAD_ACTION_ADD, flags);
cleanup:
virDomainObjEndAPI(&vm);
@@ -5973,6 +6065,48 @@ qemuDomainAddIOThread(virDomainPtr dom,
static int
+qemuDomainModIOThreadParams(virDomainPtr dom,
+ unsigned int iothread_id,
+ virTypedParameterPtr params,
+ int nparams,
+ unsigned int flags)
+{
+ virQEMUDriverPtr driver = dom->conn->privateData;
+ virDomainObjPtr vm = NULL;
+ virDomainIOThreadIDDef iothread = {0};
+ int ret = -1;
+
+ virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+ VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+ if (iothread_id == 0) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("invalid value of 0 for iothread_id"));
+ goto cleanup;
+ }
+
+ iothread.iothread_id = iothread_id;
+
+ if (!(vm = qemuDomObjFromDomain(dom)))
+ goto cleanup;
+
+ if (qemuDomainIOThreadParseParams(params, nparams, vm->privateData,
+ &iothread) < 0)
+ goto cleanup;
+
+ if (virDomainModIOThreadParamsEnsureACL(dom->conn, vm->def, flags) < 0)
+ goto cleanup;
+
+ ret = qemuDomainChgIOThread(driver, vm, iothread,
+ VIR_DOMAIN_IOTHREAD_ACTION_MOD, flags);
+
+ cleanup:
+ virDomainObjEndAPI(&vm);
+ return ret;
+}
+
+
+static int
qemuDomainDelIOThread(virDomainPtr dom,
unsigned int iothread_id,
unsigned int flags)
@@ -5998,7 +6132,8 @@ qemuDomainDelIOThread(virDomainPtr dom,
if (virDomainDelIOThreadEnsureACL(dom->conn, vm->def, flags) < 0)
goto cleanup;
- ret = qemuDomainChgIOThread(driver, vm, iothread, false, flags);
+ ret = qemuDomainChgIOThread(driver, vm, iothread,
+ VIR_DOMAIN_IOTHREAD_ACTION_DEL, flags);
cleanup:
virDomainObjEndAPI(&vm);
@@ -20366,6 +20501,7 @@ static virHypervisorDriver qemuHypervisorDriver = {
.domainPinIOThread = qemuDomainPinIOThread, /* 1.2.14 */
.domainAddIOThread = qemuDomainAddIOThread, /* 1.2.15 */
.domainAddIOThreadParams = qemuDomainAddIOThreadParams, /* 3.1.0 */
+ .domainModIOThreadParams = qemuDomainModIOThreadParams, /* 3.1.0 */
.domainDelIOThread = qemuDomainDelIOThread, /* 1.2.15 */
.domainGetSecurityLabel = qemuDomainGetSecurityLabel, /* 0.6.1 */
.domainGetSecurityLabelList = qemuDomainGetSecurityLabelList, /* 0.10.0 */
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 7633e6fc07..19be1bbf2e 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -4054,6 +4054,25 @@ qemuMonitorGetIOThreads(qemuMonitorPtr mon,
/**
+ * qemuMonitorSetIOThread:
+ * @mon: Pointer to the monitor
+ * @iothreadInfo: filled IOThread info with data
+ *
+ *
+ */
+int
+qemuMonitorSetIOThread(qemuMonitorPtr mon,
+ qemuMonitorIOThreadInfoPtr iothreadInfo)
+{
+ VIR_DEBUG("iothread=%p", iothreadInfo);
+
+ QEMU_CHECK_MONITOR_JSON(mon);
+
+ return qemuMonitorJSONSetIOThread(mon, iothreadInfo);
+}
+
+
+/**
* qemuMonitorGetMemoryDeviceInfo:
* @mon: pointer to the monitor
* @info: Location to return the hash of qemuMonitorMemoryDeviceInfo
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index eeae18e5b0..09c1dbc882 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -1013,6 +1013,9 @@ int qemuMonitorGetIOThreads(qemuMonitorPtr mon,
qemuMonitorIOThreadInfoPtr **iothreads,
bool supportPolling);
+int qemuMonitorSetIOThread(qemuMonitorPtr mon,
+ qemuMonitorIOThreadInfoPtr iothreadInfo);
+
typedef struct _qemuMonitorMemoryDeviceInfo qemuMonitorMemoryDeviceInfo;
typedef qemuMonitorMemoryDeviceInfo *qemuMonitorMemoryDeviceInfoPtr;
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index ab73f7aaf6..93e2920d79 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -6840,6 +6840,38 @@ qemuMonitorJSONGetIOThreads(qemuMonitorPtr mon,
int
+qemuMonitorJSONSetIOThread(qemuMonitorPtr mon,
+ qemuMonitorIOThreadInfoPtr iothreadInfo)
+{
+ int ret = -1;
+ char *path = NULL;
+ qemuMonitorJSONObjectProperty prop;
+
+ if (virAsprintf(&path, "/objects/iothread%u",
iothreadInfo->iothread_id) < 0)
+ goto cleanup;
+
+#define VIR_IOTHREAD_SET_PROP(propName, propVal) \
+ memset(&prop, 0, sizeof(qemuMonitorJSONObjectProperty)); \
+ prop.type = QEMU_MONITOR_OBJECT_PROPERTY_INT; \
+ prop.val.iv = propVal; \
+ if (qemuMonitorJSONSetObjectProperty(mon, path, propName, &prop) < 0) \
+ goto cleanup;
+
+ VIR_IOTHREAD_SET_PROP("poll-max-ns", iothreadInfo->poll_max_ns)
+ VIR_IOTHREAD_SET_PROP("poll-grow", iothreadInfo->poll_grow)
+ VIR_IOTHREAD_SET_PROP("poll-shrink", iothreadInfo->poll_shrink)
+
+#undef VIR_IOTHREAD_SET_PROP
+
+ ret = 0;
+
+ cleanup:
+ VIR_FREE(path);
+ return ret;
+}
+
+
+int
qemuMonitorJSONGetMemoryDeviceInfo(qemuMonitorPtr mon,
virHashTablePtr info)
{
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index 0f557a2991..1614ff5860 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -484,6 +484,10 @@ int qemuMonitorJSONGetIOThreads(qemuMonitorPtr mon,
bool supportPolling)
ATTRIBUTE_NONNULL(2);
+int qemuMonitorJSONSetIOThread(qemuMonitorPtr mon,
+ qemuMonitorIOThreadInfoPtr iothreadInfo)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+
int qemuMonitorJSONGetMemoryDeviceInfo(qemuMonitorPtr mon,
virHashTablePtr info)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
--
2.11.1