[libvirt] [PATCH v5 01/10] conf: Add new domain XML element 'iothreadids'

John Ferlan jferlan at redhat.com
Fri Apr 24 16:05:53 UTC 2015


Adding a new XML element 'iothreadids' in order to allow defining
specific IOThread ID's rather than relying on the algorithm to assign
IOThread ID's starting at 1 and incrementing to iothreads count.

This will allow future patches to be able to add new IOThreads by
a specific iothread_id and of course delete any exisiting IOThread.

Each iothreadids element will have 'n' <iothread> children elements
which will have attribute "id".  The "id" will allow for definition
of any "valid" (eg > 0) iothread_id value.

On input, if any <iothreadids> <iothread>'s are provided, they will
be marked so that we only print out what we read in.

On input, if no <iothreadids> are provided, the PostParse code will
self generate a list of ID's starting at 1 and going to the number
of iothreads defined for the domain (just like the current algorithm
numbering scheme).  A future patch will rework the existing algorithm
to make use of the iothreadids list.

On output, only print out the <iothreadids> if they were read in.

Signed-off-by: John Ferlan <jferlan at redhat.com>
---
 docs/formatdomain.html.in     |  30 +++++++
 docs/schemas/domaincommon.rng |  12 +++
 src/conf/domain_conf.c        | 203 +++++++++++++++++++++++++++++++++++++++++-
 src/conf/domain_conf.h        |  18 ++++
 src/libvirt_private.syms      |   4 +
 5 files changed, 265 insertions(+), 2 deletions(-)

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index e921749..518f7c5 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -521,6 +521,18 @@
   ...
 </domain>
 </pre>
+<pre>
+<domain>
+  ...
+  <iothreadids>
+    <iothread id="2"/>
+    <iothread id="4"/>
+    <iothread id="6"/>
+    <iothread id="8"/>
+  </iothreadids>
+  ...
+</domain>
+</pre>
 
     <dl>
       <dt><code>iothreads</code></dt>
@@ -530,7 +542,25 @@
         virtio-blk-pci and virtio-blk-ccw target storage devices. There
         should be only 1 or 2 IOThreads per host CPU. There may be more
         than one supported device assigned to each IOThread.
+        <span class="since">Since 1.2.8</span>
       </dd>
+      <dt><code>iothreadids</code></dt>
+      <dd>
+        The optional <code>iothreadids</code> element provides the capability
+        to specifically define the IOThread ID's for the domain.  By default,
+        IOThread ID's are sequentially numbered starting from 1 through the
+        number of <code>iothreads</code> defined for the domain. The
+        <code>id</code> attribute is used to define the IOThread ID. The
+        <code>id</code> attribute must be a positive integer greater than 0.
+        If there are less <code>iothreadids</code> defined than
+        <code>iothreads</code> defined for the domain, then libvirt will
+        sequentially fill <code>iothreadids</code> starting at 1 avoiding
+        any predefined <code>id</code>. If there are more
+        <code>iothreadids</code> defined than <code>iothreads</code>
+        defined for the domain, then the <code>iothreads</code> value
+        will be adjusted accordingly.
+        <span class="since">Since 1.2.15</span>
+       </dd>
     </dl>
 
     <h3><a name="elementsCPUTuning">CPU Tuning</a></h3>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 19461f5..7072954 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -539,6 +539,18 @@
       </optional>
 
       <optional>
+        <element name="iothreadids">
+          <zeroOrMore>
+            <element name="iothread">
+              <attribute name="id">
+                <ref name="unsignedInt"/>
+              </attribute>
+            </element>
+          </zeroOrMore>
+        </element>
+      </optional>
+
+      <optional>
         <ref name="blkiotune"/>
       </optional>
 
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index fb7594f..b84a447 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2102,6 +2102,32 @@ virDomainPinDefCopy(virDomainPinDefPtr *src, int npin)
     return NULL;
 }
 
+
+void
+virDomainIOThreadIDDefFree(virDomainIOThreadIDDefPtr def)
+{
+    if (!def)
+        return;
+    VIR_FREE(def);
+}
+
+
+static void
+virDomainIOThreadIDDefArrayFree(virDomainIOThreadIDDefPtr *def,
+                                int nids)
+{
+    size_t i;
+
+    if (!def)
+        return;
+
+    for (i = 0; i < nids; i++)
+        virDomainIOThreadIDDefFree(def[i]);
+
+    VIR_FREE(def);
+}
+
+
 void
 virDomainPinDefFree(virDomainPinDefPtr def)
 {
@@ -2298,6 +2324,8 @@ void virDomainDefFree(virDomainDefPtr def)
 
     virCPUDefFree(def->cpu);
 
+    virDomainIOThreadIDDefArrayFree(def->iothreadids, def->niothreadids);
+
     virDomainPinDefArrayFree(def->cputune.vcpupin, def->cputune.nvcpupin);
 
     virDomainPinDefFree(def->cputune.emulatorpin);
@@ -13169,6 +13197,54 @@ virDomainIdmapDefParseXML(xmlXPathContextPtr ctxt,
     return idmap;
 }
 
+/* Parse the XML definition for an IOThread ID
+ *
+ * Format is :
+ *
+ *     <iothreads>4</iothreads>
+ *     <iothreadids>
+ *       <iothread id='1'/>
+ *       <iothread id='3'/>
+ *       <iothread id='5'/>
+ *       <iothread id='7'/>
+ *     </iothreadids>
+ */
+static virDomainIOThreadIDDefPtr
+virDomainIOThreadIDDefParseXML(xmlNodePtr node,
+                               xmlXPathContextPtr ctxt)
+{
+    virDomainIOThreadIDDefPtr iothrid;
+    xmlNodePtr oldnode = ctxt->node;
+    char *tmp = NULL;
+
+    if (VIR_ALLOC(iothrid) < 0)
+        return NULL;
+
+    ctxt->node = node;
+
+    if (!(tmp = virXPathString("string(./@id)", ctxt))) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("Missing 'id' attribute in <iothread> element"));
+        goto error;
+    }
+    if (virStrToLong_uip(tmp, NULL, 10, &iothrid->iothread_id) < 0 ||
+        iothrid->iothread_id == 0) {
+        virReportError(VIR_ERR_XML_ERROR,
+                        _("invalid iothread 'id' value '%s'"), tmp);
+        goto error;
+    }
+
+ cleanup:
+    VIR_FREE(tmp);
+    ctxt->node = oldnode;
+    return iothrid;
+
+ error:
+    virDomainIOThreadIDDefFree(iothrid);
+    goto cleanup;
+}
+
+
 /* Parse the XML definition for a vcpupin
  *
  * vcpupin has the form of
@@ -13975,6 +14051,49 @@ virDomainDefParseXML(xmlDocPtr xml,
     }
     VIR_FREE(tmp);
 
+    /* Extract any iothread id's defined */
+    if ((n = virXPathNodeSet("./iothreadids/iothread", ctxt, &nodes)) < 0)
+        goto error;
+
+    if (n > def->iothreads)
+        def->iothreads = n;
+
+    if (n && VIR_ALLOC_N(def->iothreadids, n) < 0)
+        goto error;
+
+    for (i = 0; i < n; i++) {
+        virDomainIOThreadIDDefPtr iothrid = NULL;
+        if (!(iothrid = virDomainIOThreadIDDefParseXML(nodes[i], ctxt)))
+            goto error;
+
+        if (virDomainIOThreadIDFind(def, iothrid->iothread_id)) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("duplicate iothread id '%u' found"),
+                           iothrid->iothread_id);
+            virDomainIOThreadIDDefFree(iothrid);
+            goto error;
+        }
+        def->iothreadids[def->niothreadids++] = iothrid;
+    }
+    VIR_FREE(nodes);
+
+    /* If no iothreadid's or not fully populated, let's finish the job
+     * here rather than in PostParseCallback
+     */
+    if (def->iothreads && def->iothreads != def->niothreadids) {
+        unsigned int iothread_id = 1;
+        while (def->niothreadids != def->iothreads) {
+            if (!virDomainIOThreadIDFind(def, iothread_id)) {
+                virDomainIOThreadIDDefPtr iothrid;
+
+                if (!(iothrid = virDomainIOThreadIDAdd(def, iothread_id)))
+                    goto error;
+                iothrid->autofill = true;
+            }
+            iothread_id++;
+        }
+    }
+
     /* Extract cpu tunables. */
     if ((n = virXPathULong("string(./cputune/shares[1])", ctxt,
                            &def->cputune.shares)) < -1) {
@@ -17259,6 +17378,67 @@ virDomainDefAddImplicitControllers(virDomainDefPtr def)
     return 0;
 }
 
+virDomainIOThreadIDDefPtr
+virDomainIOThreadIDFind(virDomainDefPtr def,
+                        unsigned int iothread_id)
+{
+    size_t i;
+
+    if (!def->iothreadids || !def->niothreadids)
+        return NULL;
+
+    for (i = 0; i < def->niothreadids; i++) {
+        if (iothread_id == def->iothreadids[i]->iothread_id)
+            return def->iothreadids[i];
+    }
+
+    return NULL;
+}
+
+virDomainIOThreadIDDefPtr
+virDomainIOThreadIDAdd(virDomainDefPtr def,
+                       unsigned int iothread_id)
+{
+    virDomainIOThreadIDDefPtr iothrid = NULL;
+
+    if (virDomainIOThreadIDFind(def, iothread_id)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("cannot duplicate iothread_id '%u' in iothreadids"),
+                       iothread_id);
+        return NULL;
+    }
+
+    if (VIR_ALLOC(iothrid) < 0)
+        goto error;
+
+    iothrid->iothread_id = iothread_id;
+
+    if (VIR_APPEND_ELEMENT_COPY(def->iothreadids, def->niothreadids,
+                                iothrid) < 0)
+        goto error;
+
+    return iothrid;
+
+ error:
+    virDomainIOThreadIDDefFree(iothrid);
+    return NULL;
+}
+
+void
+virDomainIOThreadIDDel(virDomainDefPtr def,
+                       unsigned int iothread_id)
+{
+    int n;
+
+    for (n = 0; n < def->niothreadids; n++) {
+        if (def->iothreadids[n]->iothread_id == iothread_id) {
+            virDomainIOThreadIDDefFree(def->iothreadids[n]);
+            VIR_DELETE_ELEMENT(def->iothreadids, n, def->niothreadids);
+            return;
+        }
+    }
+}
+
 /* Check if vcpupin with same id already exists. */
 bool
 virDomainPinIsDuplicate(virDomainPinDefPtr *def,
@@ -20601,8 +20781,27 @@ virDomainDefFormatInternal(virDomainDefPtr def,
         virBufferAsprintf(buf, " current='%u'", def->vcpus);
     virBufferAsprintf(buf, ">%u</vcpu>\n", def->maxvcpus);
 
-    if (def->iothreads > 0)
-        virBufferAsprintf(buf, "<iothreads>%u</iothreads>\n", def->iothreads);
+    if (def->iothreads > 0) {
+        virBufferAsprintf(buf, "<iothreads>%u</iothreads>\n",
+                          def->iothreads);
+        /* Only print out iothreadids if we read at least one */
+        for (i = 0; i < def->niothreadids; i++) {
+            if (!def->iothreadids[i]->autofill)
+                break;
+        }
+        if (i < def->niothreadids) {
+            virBufferAddLit(buf, "<iothreadids>\n");
+            virBufferAdjustIndent(buf, 2);
+            for (i = 0; i < def->niothreadids; i++) {
+                if (def->iothreadids[i]->autofill)
+                    continue;
+                virBufferAsprintf(buf, "<iothread id='%u'/>\n",
+                                  def->iothreadids[i]->iothread_id);
+            }
+            virBufferAdjustIndent(buf, -2);
+            virBufferAddLit(buf, "</iothreadids>\n");
+        }
+    }
 
     if (def->cputune.sharesSpecified ||
         (def->cputune.nvcpupin && !virDomainIsAllVcpupinInherited(def)) ||
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 9955052..28a003e 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2054,6 +2054,16 @@ struct _virDomainHugePage {
     unsigned long long size;    /* hugepage size in KiB */
 };
 
+typedef struct _virDomainIOThreadIDDef virDomainIOThreadIDDef;
+typedef virDomainIOThreadIDDef *virDomainIOThreadIDDefPtr;
+
+struct _virDomainIOThreadIDDef {
+    bool autofill;
+    unsigned int iothread_id;
+};
+
+void virDomainIOThreadIDDefFree(virDomainIOThreadIDDefPtr def);
+
 typedef struct _virDomainCputune virDomainCputune;
 typedef virDomainCputune *virDomainCputunePtr;
 
@@ -2145,6 +2155,8 @@ struct _virDomainDef {
     virBitmapPtr cpumask;
 
     unsigned int iothreads;
+    size_t niothreadids;
+    virDomainIOThreadIDDefPtr *iothreadids;
 
     virDomainCputune cputune;
 
@@ -2604,6 +2616,12 @@ bool virDomainDefCheckABIStability(virDomainDefPtr src,
 
 int virDomainDefAddImplicitControllers(virDomainDefPtr def);
 
+virDomainIOThreadIDDefPtr virDomainIOThreadIDFind(virDomainDefPtr def,
+                                                  unsigned int iothread_id);
+virDomainIOThreadIDDefPtr virDomainIOThreadIDAdd(virDomainDefPtr def,
+                                                 unsigned int iothread_id);
+void virDomainIOThreadIDDel(virDomainDefPtr def, unsigned int iothread_id);
+
 unsigned int virDomainDefFormatConvertXMLFlags(unsigned int flags);
 
 char *virDomainDefFormat(virDomainDefPtr def,
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index e6555f1..1c345fc 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -324,6 +324,10 @@ virDomainHubTypeToString;
 virDomainHypervTypeFromString;
 virDomainHypervTypeToString;
 virDomainInputDefFree;
+virDomainIOThreadIDAdd;
+virDomainIOThreadIDDefFree;
+virDomainIOThreadIDDel;
+virDomainIOThreadIDFind;
 virDomainLeaseDefFree;
 virDomainLeaseIndex;
 virDomainLeaseInsert;
-- 
2.1.0




More information about the libvir-list mailing list