[PATCH 4/6] conf: Add possibility to configure multiple iothreads per disk

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Introduce a new <iothreads> sub-element of disk's <driver> which will
allow configuring multiple iothreads and also map them to specific
virt-queues of virtio devices.

Signed-off-by: Peter Krempa <pkrempa@xxxxxxxxxx>
---
 docs/formatdomain.rst             | 23 +++++++++-
 src/conf/domain_conf.c            | 76 +++++++++++++++++++++++++++++++
 src/conf/domain_conf.h            | 14 ++++++
 src/conf/domain_validate.c        |  8 ++++
 src/conf/schemas/domaincommon.rng | 47 ++++++++++++++-----
 5 files changed, 155 insertions(+), 13 deletions(-)

diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 96e03a3807..b8a12c2ab3 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -3338,7 +3338,28 @@ paravirtualized driver is specified via the ``disk`` element.
       assigned to the same IOThread and are numbered from 1 to the domain
       iothreads value. Available for a disk device ``target`` configured to use
       "virtio" ``bus`` and "pci" or "ccw" ``address`` types. :since:`Since 1.2.8
-      (QEMU 2.1)`
+      (QEMU 2.1)` *Note:* ``iothread`` is mutually exclusive with ``iothreads``.
+   -  The optional ``iothreads`` sub-element allows specifying multiple IOThreads
+      via the ``iothread`` sub-element with attribute ``id``  the disk will use
+      for I/O operations. Optionally the ``iothread`` element can have multiple
+      ``queue`` subelements specifying that given iothread should be used to
+      handle given queues. :since:`Since 10.0.0 (QEMU 9.0, virtio disks only)`.
+      Example::
+
+        <driver name='qemu' queues='2'>
+          <iothreads>
+            <iothread id='1'>
+              <queue id='1'/>
+            </iothread>
+            <iothread id='2'>
+              <queue id='1'/>
+            </iothread>
+            <iothread id='3'>
+              <queue id='2'/>
+            </iothread>
+          </iothreads>
+        </driver>
+
    -  The optional ``queues`` attribute specifies the number of virt queues for
       virtio-blk ( :since:`Since 3.9.0` ) or vhost-user-blk
       ( :since `Since 7.1.0` )
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index db3d12cb49..aab37b4304 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2337,6 +2337,17 @@ virDomainDefGetVcpusTopology(const virDomainDef *def,
 }


+void
+virDomainDiskIothreadDefFree(virDomainDiskIothreadDef *def)
+{
+    if (!def)
+        return;
+
+    g_free(def->queues);
+    g_free(def);
+}
+
+
 static virDomainDiskDef *
 virDomainDiskDefNewSource(virDomainXMLOption *xmlopt,
                           virStorageSource **src)
@@ -2385,6 +2396,7 @@ virDomainDiskDefFree(virDomainDiskDef *def)
     g_free(def->virtio);
     virDomainDeviceInfoClear(&def->info);
     virObjectUnref(def->privateData);
+    g_slist_free_full(def->iothreads, (GDestroyNotify) virDomainDiskIothreadDefFree);

     g_free(def);
 }
@@ -7775,6 +7787,8 @@ static int
 virDomainDiskDefDriverParseXML(virDomainDiskDef *def,
                                xmlNodePtr cur)
 {
+    xmlNodePtr iothreadsNode;
+
     def->driverName = virXMLPropString(cur, "name");

     if (virXMLPropEnum(cur, "cache", virDomainDiskCacheTypeFromString,
@@ -7821,6 +7835,44 @@ virDomainDiskDefDriverParseXML(virDomainDiskDef *def,
     if (virXMLPropUInt(cur, "iothread", 10, VIR_XML_PROP_NONZERO, &def->iothread) < 0)
         return -1;

+    if ((iothreadsNode = virXMLNodeGetSubelement(cur, "iothreads"))) {
+        g_autoslist(virDomainDiskIothreadDef) ioth = NULL;
+        g_autoptr(GPtrArray) iothreadNodes = NULL;
+
+        if ((iothreadNodes = virXMLNodeGetSubelementList(iothreadsNode, "iothread"))) {
+            size_t i;
+
+            for (i = 0; i < iothreadNodes->len; i++) {
+                xmlNodePtr iothNode = g_ptr_array_index(iothreadNodes, i);
+                g_autoptr(virDomainDiskIothreadDef) iothdef = g_new0(virDomainDiskIothreadDef, 1);
+                g_autoptr(GPtrArray) queueNodes = NULL;
+
+                if (virXMLPropUInt(iothNode, "id", 10, VIR_XML_PROP_REQUIRED,
+                                   &iothdef->id) < 0)
+                    return -1;
+
+                if ((queueNodes = virXMLNodeGetSubelementList(iothNode, "queue"))) {
+                    size_t q;
+
+                    iothdef->queues = g_new0(unsigned int, queueNodes->len);
+                    iothdef->nqueues = queueNodes->len;
+
+                    for (q = 0; q < queueNodes->len; q++) {
+                        xmlNodePtr queueNode = g_ptr_array_index(queueNodes, q);
+
+                        if (virXMLPropUInt(queueNode, "id", 10, VIR_XML_PROP_REQUIRED,
+                                           &(iothdef->queues[q])) < 0)
+                            return -1;
+                    }
+                }
+
+                ioth = g_slist_prepend(ioth, g_steal_pointer(&iothdef));
+            }
+
+            def->iothreads = g_slist_reverse(g_steal_pointer(&ioth));
+        }
+    }
+
     if (virXMLPropEnum(cur, "detect_zeroes",
                        virDomainDiskDetectZeroesTypeFromString,
                        VIR_XML_PROP_NONZERO, &def->detect_zeroes) < 0)
@@ -22715,6 +22767,30 @@ virDomainDiskDefFormatDriver(virBuffer *buf,
         virXMLFormatElement(&childBuf, "metadata_cache", NULL, &metadataCacheChildBuf);
     }

+    if (disk->iothreads) {
+        g_auto(virBuffer) iothreadsChildBuf = VIR_BUFFER_INIT_CHILD(&childBuf);
+        GSList *n;
+
+        for (n = disk->iothreads; n; n = n->next) {
+            virDomainDiskIothreadDef *iothDef = n->data;
+            g_auto(virBuffer) iothreadAttrBuf = VIR_BUFFER_INITIALIZER;
+            g_auto(virBuffer) iothreadChildBuf = VIR_BUFFER_INIT_CHILD(&iothreadsChildBuf);
+
+            virBufferAsprintf(&iothreadAttrBuf, " id='%u'", iothDef->id);
+
+            if (iothDef->queues) {
+                size_t q;
+
+                for (q = 0; q < iothDef->nqueues; q++)
+                    virBufferAsprintf(&iothreadChildBuf, "<queue id='%u'/>\n", iothDef->queues[q]);
+            }
+
+            virXMLFormatElement(&iothreadsChildBuf, "iothread", &iothreadAttrBuf, &iothreadChildBuf);
+        }
+
+        virXMLFormatElement(&childBuf, "iothreads", NULL, &iothreadsChildBuf);
+    }
+
     virXMLFormatElement(buf, "driver", &attrBuf, &childBuf);
 }

diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 14901b37ba..a5757ae808 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -515,6 +515,19 @@ typedef enum {
 VIR_ENUM_DECL(virDomainSnapshotLocation);


+struct _virDomainDiskIothreadDef {
+    unsigned int id;
+
+    /* optional list of virtqueues the iothread should handle */
+    unsigned int *queues;
+    size_t nqueues;
+};
+
+typedef struct _virDomainDiskIothreadDef virDomainDiskIothreadDef;
+void virDomainDiskIothreadDefFree(virDomainDiskIothreadDef *def);
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainDiskIothreadDef, virDomainDiskIothreadDefFree);
+
+
 /* Stores the virtual disk configuration */
 struct _virDomainDiskDef {
     virStorageSource *src; /* non-NULL.  XXX Allow NULL for empty cdrom? */
@@ -569,6 +582,7 @@ struct _virDomainDiskDef {
     virDomainDeviceSGIO sgio;
     virDomainDiskDiscard discard;
     unsigned int iothread; /* unused = 0, > 0 specific thread # */
+    GSList *iothreads; /* List of virDomainDiskIothreadsDef */
     virDomainDiskDetectZeroes detect_zeroes;
     virTristateSwitch discard_no_unref;
     char *domain_name; /* backend domain name */
diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
index c72108886e..d485ec4fb1 100644
--- a/src/conf/domain_validate.c
+++ b/src/conf/domain_validate.c
@@ -934,6 +934,14 @@ virDomainDiskDefValidate(const virDomainDef *def,
         }
     }

+    /* configuring both <driver iothread='n'> and it's <iothreads> sub-element
+     * isn't supported */
+    if (disk->iothread && disk->iothreads) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("disk driver 'iothread' attribute can't be used together with 'iothreads' subelement"));
+        return -1;
+    }
+
     return 0;
 }

diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
index f318c06797..3f856452cf 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -2536,9 +2536,26 @@
       </optional>
     </element>
   </define>
-  <!--
-      Disk may use a special driver for access.
-    -->
+
+  <define name="diskDriverIothreads">
+    <element name="iothreads">
+      <oneOrMore>
+        <element name="iothread">
+          <attribute name="id">
+            <ref name="unsignedInt"/>
+          </attribute>
+          <zeroOrMore>
+            <element name="queue">
+              <attribute name="id">
+                <ref name="unsignedInt"/>
+              </attribute>
+            </element>
+          </zeroOrMore>
+        </element>
+      </oneOrMore>
+    </element>
+  </define>
+
   <define name="diskDriver">
     <element name="driver">
       <optional>
@@ -2590,17 +2607,23 @@
         </attribute>
       </optional>
       <ref name="virtioOptions"/>
-      <optional>
-        <element name="metadata_cache">
-          <optional>
-            <element name="max_size">
-              <ref name="scaledInteger"/>
-            </element>
-          </optional>
-        </element>
-      </optional>
+      <interleave>
+        <optional>
+          <element name="metadata_cache">
+            <optional>
+              <element name="max_size">
+                <ref name="scaledInteger"/>
+              </element>
+            </optional>
+          </element>
+        </optional>
+        <optional>
+          <ref name="diskDriverIothreads"/>
+        </optional>
+      </interleave>
     </element>
   </define>
+
   <define name="driverFormat">
     <optional>
       <attribute name="name">
-- 
2.43.0
_______________________________________________
Devel mailing list -- devel@xxxxxxxxxxxxxxxxx
To unsubscribe send an email to devel-leave@xxxxxxxxxxxxxxxxx




[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]

  Powered by Linux