diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 312b605a8b..07837220ed 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -675,7 +675,7 @@ host/guest with many LUNs. :since:`Since 1.2.8 (QEMU only)`
-
+
...
@@ -696,6 +696,10 @@ host/guest with many LUNs. :since:`Since 1.2.8 (QEMU only)`
any predefined ``id``. If there are more ``iothreadids`` defined than
``iothreads`` defined for the domain, then the ``iothreads`` value will be
adjusted accordingly. :since:`Since 1.2.15`
+ The element has two optional attributes ``thread_pool_min`` and
+ ``thread_pool_max`` which allow setting lower and upper boundary for number
+ of worker threads for given IOThread. While the former can be value of zero,
+ the latter can't. :since:`Since 8.5.0`
CPU Tuning
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index f3923cf2ba..ea8061dc3d 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -3482,6 +3482,9 @@ virDomainIOThreadIDDefNew(void)
{
virDomainIOThreadIDDef *def = g_new0(virDomainIOThreadIDDef, 1);
+ def->thread_pool_min = -1;
+ def->thread_pool_max = -1;
+
return def;
}
@@ -17009,7 +17012,7 @@ virDomainIdmapDefParseXML(xmlXPathContextPtr ctxt,
*
* 4
*
- *
+ *
*
*
*
@@ -17025,6 +17028,16 @@ virDomainIOThreadIDDefParseXML(xmlNodePtr node)
&iothrid->iothread_id) < 0)
return NULL;
+ if (virXMLPropInt(node, "thread_pool_min", 10,
+ VIR_XML_PROP_NONNEGATIVE,
+ &iothrid->thread_pool_min, -1) < 0)
+ return NULL;
+
+ if (virXMLPropInt(node, "thread_pool_max", 10,
+ VIR_XML_PROP_NONNEGATIVE,
+ &iothrid->thread_pool_max, -1) < 0)
+ return NULL;
+
return g_steal_pointer(&iothrid);
}
@@ -27608,8 +27621,23 @@ virDomainDefIOThreadsFormat(virBuffer *buf,
return;
for (i = 0; i < def->niothreadids; i++) {
- virBufferAsprintf(&childrenBuf, "\n",
- def->iothreadids[i]->iothread_id);
+ virDomainIOThreadIDDef *iothread = def->iothreadids[i];
+ g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
+
+ virBufferAsprintf(&attrBuf, " id='%u'",
+ iothread->iothread_id);
+
+ if (iothread->thread_pool_min >= 0) {
+ virBufferAsprintf(&attrBuf, " thread_pool_min='%d'",
+ iothread->thread_pool_min);
+ }
+
+ if (iothread->thread_pool_max >= 0) {
+ virBufferAsprintf(&attrBuf, " thread_pool_max='%d'",
+ iothread->thread_pool_max);
+ }
+
+ virXMLFormatElement(&childrenBuf, "iothread", &attrBuf, NULL);
}
virXMLFormatElement(buf, "iothreadids", NULL, &childrenBuf);
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 1efdb439ac..035edc0710 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2646,6 +2646,9 @@ struct _virDomainIOThreadIDDef {
virBitmap *cpumask;
virDomainThreadSchedParam sched;
+
+ int thread_pool_min;
+ int thread_pool_max;
};
void virDomainIOThreadIDDefFree(virDomainIOThreadIDDef *def);
diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
index f3910f08a4..3ada739ea7 100644
--- a/src/conf/domain_validate.c
+++ b/src/conf/domain_validate.c
@@ -1716,6 +1716,31 @@ virDomainDefFSValidate(const virDomainDef *def)
}
+static int
+virDomainDefValidateIOThreads(const virDomainDef *def)
+{
+ size_t i;
+
+ for (i = 0; i < def->niothreadids; i++) {
+ virDomainIOThreadIDDef *iothread = def->iothreadids[i];
+
+ if (iothread->thread_pool_max == 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("thread_pool_max must be a positive integer"));
+ return -1;
+ }
+
+ if (iothread->thread_pool_min > iothread->thread_pool_max) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("thread_pool_min must be smaller or equal to thread_pool_max"));
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
static int
virDomainDefValidateInternal(const virDomainDef *def,
virDomainXMLOption *xmlopt)
@@ -1771,6 +1796,9 @@ virDomainDefValidateInternal(const virDomainDef *def,
if (virDomainDefFSValidate(def) < 0)
return -1;
+ if (virDomainDefValidateIOThreads(def) < 0)
+ return -1;
+
return 0;
}
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
index cc598212a8..fad70d3857 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -829,6 +829,16 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/qemuxml2argvdata/iothreads-ids-pool-sizes.xml b/tests/qemuxml2argvdata/iothreads-ids-pool-sizes.xml
new file mode 100644
index 0000000000..0f93d14f12
--- /dev/null
+++ b/tests/qemuxml2argvdata/iothreads-ids-pool-sizes.xml
@@ -0,0 +1,61 @@
+
+ QEMUGuest1
+ c7a5fdbd-edaf-9455-926a-d65c16db1809
+ 219136
+ 219136
+ 6
+ 5
+
+
+
+
+
+
+
+
+ hvm
+
+
+
+ qemu64
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu-system-x86_64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/qemuxml2xmloutdata/iothreads-ids-pool-sizes.x86_64-latest.xml b/tests/qemuxml2xmloutdata/iothreads-ids-pool-sizes.x86_64-latest.xml
new file mode 120000
index 0000000000..6ed642fe5f
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/iothreads-ids-pool-sizes.x86_64-latest.xml
@@ -0,0 +1 @@
+../qemuxml2argvdata/iothreads-ids-pool-sizes.xml
\ No newline at end of file
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 3bd57306cc..b85d5fb757 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -597,6 +597,7 @@ mymain(void)
DO_TEST_NOCAPS("smp");
DO_TEST_NOCAPS("iothreads");
DO_TEST_NOCAPS("iothreads-ids");
+ DO_TEST_CAPS_LATEST("iothreads-ids-pool-sizes");
DO_TEST_NOCAPS("iothreads-ids-partial");
DO_TEST_NOCAPS("cputune-iothreads");
DO_TEST_NOCAPS("iothreads-disk");