]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
conf: Introduce thread_pool_min and thread_pool_max attributes to IOThread
authorMichal Privoznik <mprivozn@redhat.com>
Mon, 7 Mar 2022 14:13:39 +0000 (15:13 +0100)
committerMichal Privoznik <mprivozn@redhat.com>
Fri, 10 Jun 2022 11:59:46 +0000 (13:59 +0200)
At least in case of QEMU an IOThread is actually a pool of
threads (see iothread_set_aio_context_params() in QEMU's code
base). As such, it can have minimal and maximal number of worker
threads. Allow setting them in domain XML.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
docs/formatdomain.rst
src/conf/domain_conf.c
src/conf/domain_conf.h
src/conf/domain_validate.c
src/conf/schemas/domaincommon.rng
tests/qemuxml2argvdata/iothreads-ids-pool-sizes.xml [new file with mode: 0644]
tests/qemuxml2xmloutdata/iothreads-ids-pool-sizes.x86_64-latest.xml [new symlink]
tests/qemuxml2xmltest.c

index 312b605a8b2d2dcd9b95556c90de48f2509227b5..07837220ed954f795ff39f74516f1ed74362ca92 100644 (file)
@@ -675,7 +675,7 @@ host/guest with many LUNs. :since:`Since 1.2.8 (QEMU only)`
        <iothread id="2"/>
        <iothread id="4"/>
        <iothread id="6"/>
-       <iothread id="8"/>
+       <iothread id="8" thread_pool_min="2" thread_pool_max="32"/>
      </iothreadids>
      ...
    </domain>
@@ -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
index f3923cf2ba2b53bda071905a2ba7437b963db646..ea8061dc3de01700889d8d64d557104a0bc66f00 100644 (file)
@@ -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,
  *
  *     <iothreads>4</iothreads>
  *     <iothreadids>
- *       <iothread id='1'/>
+ *       <iothread id='1' thread_pool_min="0" thread_pool_max="60"/>
  *       <iothread id='3'/>
  *       <iothread id='5'/>
  *       <iothread id='7'/>
@@ -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, "<iothread id='%u'/>\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);
index 1efdb439ac2d161d8b6df84241d56c3ef12e426e..035edc0710f3ad468a534c5ef6921cf65cb80651 100644 (file)
@@ -2646,6 +2646,9 @@ struct _virDomainIOThreadIDDef {
     virBitmap *cpumask;
 
     virDomainThreadSchedParam sched;
+
+    int thread_pool_min;
+    int thread_pool_max;
 };
 
 void virDomainIOThreadIDDefFree(virDomainIOThreadIDDef *def);
index f3910f08a4b187caa5004d6be51cc5259364ee47..3ada739ea748b004c4bcc63da4506f4871919611 100644 (file)
@@ -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;
 }
 
index cc598212a8e4762430b91c4730c80cae83185dc9..fad70d385756b983897095efd2f0ad0cb7a18d6f 100644 (file)
               <attribute name="id">
                 <ref name="unsignedInt"/>
               </attribute>
+              <optional>
+                <attribute name="thread_pool_min">
+                  <ref name="unsignedInt"/>
+                </attribute>
+              </optional>
+              <optional>
+                <attribute name="thread_pool_max">
+                  <ref name="unsignedInt"/>
+                </attribute>
+              </optional>
             </element>
           </zeroOrMore>
         </element>
diff --git a/tests/qemuxml2argvdata/iothreads-ids-pool-sizes.xml b/tests/qemuxml2argvdata/iothreads-ids-pool-sizes.xml
new file mode 100644 (file)
index 0000000..0f93d14
--- /dev/null
@@ -0,0 +1,61 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>6</vcpu>
+  <iothreads>5</iothreads>
+  <iothreadids>
+    <iothread id='2' thread_pool_min='0' thread_pool_max='60'/>
+    <iothread id='4' thread_pool_min='1' thread_pool_max='1'/>
+    <iothread id='1'/>
+    <iothread id='3'/>
+    <iothread id='5'/>
+  </iothreadids>
+  <os>
+    <type arch='x86_64' machine='q35'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <cpu mode='custom' match='exact' check='none'>
+    <model fallback='forbid'>qemu64</model>
+  </cpu>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-x86_64</emulator>
+    <disk type='block' device='disk'>
+      <driver name='qemu' type='raw'/>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='vda' bus='virtio'/>
+      <address type='pci' domain='0x0000' bus='0x02' slot='0x00' function='0x0'/>
+    </disk>
+    <controller type='pci' index='0' model='pcie-root'/>
+    <controller type='pci' index='1' model='pcie-root-port'>
+      <model name='pcie-root-port'/>
+      <target chassis='1' port='0x8'/>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0' multifunction='on'/>
+    </controller>
+    <controller type='pci' index='2' model='pcie-root-port'>
+      <model name='pcie-root-port'/>
+      <target chassis='2' port='0x9'/>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
+    </controller>
+    <controller type='pci' index='3' model='pcie-root-port'>
+      <model name='pcie-root-port'/>
+      <target chassis='3' port='0xa'/>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
+    </controller>
+    <controller type='usb' index='0' model='qemu-xhci'>
+      <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
+    </controller>
+    <controller type='sata' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/>
+    </controller>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <audio id='1' type='none'/>
+    <memballoon model='none'/>
+  </devices>
+</domain>
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 (symlink)
index 0000000..6ed642f
--- /dev/null
@@ -0,0 +1 @@
+../qemuxml2argvdata/iothreads-ids-pool-sizes.xml
\ No newline at end of file
index 3bd57306ccf73d9a0a0e378797c2148b0dc13959..b85d5fb757885b71b45451eeb32754a2e358b2a5 100644 (file)
@@ -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");