diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index ee1adb0300..ded34e97cd 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -5323,6 +5323,26 @@ qemuDomainHotplugModIOThread(virQEMUDriver *driver, } +static int +qemuDomainHotplugModIOThreadIDDef(virDomainIOThreadIDDef *def, + qemuMonitorIOThreadInfo mondef) +{ + /* These have no representation in domain XML */ + if (mondef.set_poll_grow || + mondef.set_poll_max_ns || + mondef.set_poll_shrink) + return -1; + + if (mondef.set_thread_pool_min) + def->thread_pool_min = mondef.thread_pool_min; + + if (mondef.set_thread_pool_max) + def->thread_pool_max = mondef.thread_pool_max; + + return 0; +} + + static int qemuDomainHotplugDelIOThread(virQEMUDriver *driver, virDomainObj *vm, @@ -5430,6 +5450,10 @@ qemuDomainIOThreadParseParams(virTypedParameterPtr params, VIR_TYPED_PARAM_UINT, VIR_DOMAIN_IOTHREAD_POLL_SHRINK, VIR_TYPED_PARAM_UINT, + VIR_DOMAIN_IOTHREAD_THREAD_POOL_MIN, + VIR_TYPED_PARAM_INT, + VIR_DOMAIN_IOTHREAD_THREAD_POOL_MAX, + VIR_TYPED_PARAM_INT, NULL) < 0) return -1; @@ -5454,6 +5478,20 @@ qemuDomainIOThreadParseParams(virTypedParameterPtr params, if (rc == 1) iothread->set_poll_shrink = true; + if ((rc = virTypedParamsGetInt(params, nparams, + VIR_DOMAIN_IOTHREAD_THREAD_POOL_MIN, + &iothread->thread_pool_min)) < 0) + return -1; + if (rc == 1) + iothread->set_thread_pool_min = true; + + if ((rc = virTypedParamsGetInt(params, nparams, + VIR_DOMAIN_IOTHREAD_THREAD_POOL_MAX, + &iothread->thread_pool_max)) < 0) + return -1; + if (rc == 1) + iothread->set_thread_pool_max = true; + if (iothread->set_poll_max_ns && iothread->poll_max_ns > INT_MAX) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("poll-max-ns (%llu) must be less than or equal to %d"), @@ -5475,6 +5513,78 @@ qemuDomainIOThreadParseParams(virTypedParameterPtr params, return -1; } + if (iothread->set_thread_pool_min && iothread->thread_pool_min < -1) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("thread_pool_min (%d) must be equal to or greater than -1"), + iothread->thread_pool_min); + return -1; + } + + if (iothread->set_thread_pool_max && + (iothread->thread_pool_max < -1 || iothread->thread_pool_max == 0)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("thread_pool_max (%d) must be a positive number or -1"), + iothread->thread_pool_max); + return -1; + } + + return 0; +} + + +/** + * qemuDomainIOThreadValidate: + * iothreaddef: IOThread definition in domain XML + * iothread: new values to set + * live: whether this is update of active domain + * + * Validate that changes to be made to an IOThread (as expressed by @iothread) + * are consistent with the current state of the IOThread (@iothreaddef). + * For instance, that thread_pool_min won't end up greater than thread_pool_max. + * + * Returns: 0 on success, + * -1 on error, with error message reported. + */ +static int +qemuDomainIOThreadValidate(virDomainIOThreadIDDef *iothreaddef, + qemuMonitorIOThreadInfo iothread, + bool live) +{ + int thread_pool_min = iothreaddef->thread_pool_min; + int thread_pool_max = iothreaddef->thread_pool_max; + + /* For live change we don't have a way to let QEMU return to its + * defaults. Therefore, deny setting -1. */ + + if (iothread.set_thread_pool_min) { + if (live && iothread.thread_pool_min < 0) { + virReportError(VIR_ERR_OPERATION_INVALID, + _("thread_pool_min (%d) must be equal to or greater than 0 for live change"), + iothread.thread_pool_min); + return -1; + } + + thread_pool_min = iothread.thread_pool_min; + } + + if (iothread.set_thread_pool_max) { + if (live && iothread.thread_pool_max < 0) { + virReportError(VIR_ERR_OPERATION_INVALID, + _("thread_pool_max (%d) must be equal to or greater than 0 for live change"), + iothread.thread_pool_max); + return -1; + } + + thread_pool_max = iothread.thread_pool_max; + } + + if (thread_pool_min > thread_pool_max) { + virReportError(VIR_ERR_OPERATION_INVALID, + _("thread_pool_min (%d) can't be greater than thread_pool_max (%d)"), + thread_pool_min, thread_pool_max); + return -1; + } + return 0; } @@ -5496,6 +5606,7 @@ qemuDomainChgIOThread(virQEMUDriver *driver, qemuDomainObjPrivate *priv; virDomainDef *def; virDomainDef *persistentDef; + virDomainIOThreadIDDef *iothreaddef = NULL; int ret = -1; cfg = virQEMUDriverGetConfig(driver); @@ -5535,16 +5646,22 @@ qemuDomainChgIOThread(virQEMUDriver *driver, break; case VIR_DOMAIN_IOTHREAD_ACTION_MOD: - if (!(virDomainIOThreadIDFind(def, iothread.iothread_id))) { + iothreaddef = virDomainIOThreadIDFind(def, iothread.iothread_id); + + if (!iothreaddef) { virReportError(VIR_ERR_INVALID_ARG, _("cannot find IOThread '%u' in iothreadids"), iothread.iothread_id); goto endjob; } + if (qemuDomainIOThreadValidate(iothreaddef, iothread, true) < 0) + goto endjob; + if (qemuDomainHotplugModIOThread(driver, vm, iothread) < 0) goto endjob; + qemuDomainHotplugModIOThreadIDDef(iothreaddef, iothread); break; } @@ -5572,10 +5689,23 @@ qemuDomainChgIOThread(virQEMUDriver *driver, break; case VIR_DOMAIN_IOTHREAD_ACTION_MOD: - virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", - _("configuring persistent polling values is " - "not supported")); - goto endjob; + iothreaddef = virDomainIOThreadIDFind(persistentDef, iothread.iothread_id); + + if (!iothreaddef) { + virReportError(VIR_ERR_INVALID_ARG, + _("cannot find IOThread '%u' in iothreadids"), + iothread.iothread_id); + goto endjob; + } + + if (qemuDomainIOThreadValidate(iothreaddef, iothread, false) < 0) + goto endjob; + + if (qemuDomainHotplugModIOThreadIDDef(iothreaddef, iothread) < 0) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("configuring persistent polling values is not supported")); + goto endjob; + } break; } diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 91f2d0941c..06822d6642 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1314,9 +1314,13 @@ struct _qemuMonitorIOThreadInfo { unsigned long long poll_max_ns; unsigned int poll_grow; unsigned int poll_shrink; + int thread_pool_min; + int thread_pool_max; bool set_poll_max_ns; bool set_poll_grow; bool set_poll_shrink; + bool set_thread_pool_min; + bool set_thread_pool_max; }; int qemuMonitorGetIOThreads(qemuMonitor *mon, qemuMonitorIOThreadInfo ***iothreads, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 8b81a07429..6b3acab0d2 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -7447,6 +7447,8 @@ qemuMonitorJSONSetIOThread(qemuMonitor *mon, VIR_IOTHREAD_SET_PROP("poll-max-ns", poll_max_ns); VIR_IOTHREAD_SET_PROP("poll-grow", poll_grow); VIR_IOTHREAD_SET_PROP("poll-shrink", poll_shrink); + VIR_IOTHREAD_SET_PROP("thread-pool-min", thread_pool_min); + VIR_IOTHREAD_SET_PROP("thread-pool-max", thread_pool_max); #undef VIR_IOTHREAD_SET_PROP