[libvirt] [PATCH 4/8] Support block I/O throtte in XML

Lei Li lilei at linux.vnet.ibm.com
Tue Nov 15 09:02:46 UTC 2011


Enable block I/O throttle for per-disk in XML.

Signed-off-by: Lei Li <lilei at linux.vnet.ibm.com>
Signed-off-by: Zhi Yong Wu <wuzhy at linux.vnet.ibm.com>
---
 src/conf/domain_conf.c  |  101 +++++++++++++++++++++++++++++++++++++++++++++-
 src/conf/domain_conf.h  |   12 ++++++
 src/qemu/qemu_command.c |   33 +++++++++++++++
 src/util/xml.h          |    2 +
 4 files changed, 145 insertions(+), 3 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 58f4d0f..a157b80 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2318,7 +2318,8 @@ static virDomainDiskDefPtr
 virDomainDiskDefParseXML(virCapsPtr caps,
                          xmlNodePtr node,
                          virBitmapPtr bootMap,
-                         unsigned int flags)
+                         unsigned int flags,
+                         xmlXPathContextPtr ctxt)
 {
     virDomainDiskDefPtr def;
     xmlNodePtr cur, child;
@@ -2517,6 +2518,62 @@ virDomainDiskDefParseXML(virCapsPtr caps,
                     }
                     child = child->next;
                 }
+            } else if (xmlStrEqual(cur->name, BAD_CAST "iotune")) {
+                if (virXPathULongLong("string(./devices/disk/iotune/total_bytes_sec)",
+                                       ctxt, &def->blkdeviotune.total_bytes_sec) < 0) {
+                    def->blkdeviotune.total_bytes_sec = 0;
+                } else {
+                    def->blkdeviotune.mark = 1;
+                }
+
+                if (virXPathULongLong("string(./devices/disk/iotune/read_bytes_sec)",
+                                       ctxt, &def->blkdeviotune.read_bytes_sec) < 0) {
+                    def->blkdeviotune.read_bytes_sec = 0;
+                } else {
+                    def->blkdeviotune.mark = 1;
+                }
+
+                if (virXPathULongLong("string(./devices/disk/iotune/write_bytes_sec)",
+                                       ctxt, &def->blkdeviotune.write_bytes_sec) < 0) {
+                    def->blkdeviotune.write_bytes_sec = 0;
+                } else {
+                    def->blkdeviotune.mark = 1;
+                }
+
+               if (virXPathULongLong("string(./devices/disk/iotune/total_iops_sec)",
+                                       ctxt, &def->blkdeviotune.total_iops_sec) < 0) {
+                    def->blkdeviotune.total_iops_sec = 0;
+                } else {
+                    def->blkdeviotune.mark = 1;
+                }
+
+                if (virXPathULongLong("string(./devices/disk/iotune/read_iops_sec)",
+                                       ctxt, &def->blkdeviotune.read_iops_sec) < 0) {
+                    def->blkdeviotune.read_iops_sec = 0;
+                } else {
+                    def->blkdeviotune.mark = 1;
+                }
+
+                if (virXPathULongLong("string(./devices/disk/iotune/write_iops_sec)",
+                                       ctxt, &def->blkdeviotune.write_iops_sec) < 0) {
+                    def->blkdeviotune.write_iops_sec = 0;
+                } else {
+                    def->blkdeviotune.mark = 1;
+                }
+
+                if ((def->blkdeviotune.total_bytes_sec && def->blkdeviotune.read_bytes_sec)
+                    || (def->blkdeviotune.total_bytes_sec && def->blkdeviotune.write_bytes_sec)) {
+                    virDomainReportError(VIR_ERR_XML_ERROR,
+                                         _("total and read/write bytes_sec cannot be set at the same time"));
+                    goto error;
+                }
+
+                if ((def->blkdeviotune.total_iops_sec && def->blkdeviotune.read_iops_sec)
+                    || (def->blkdeviotune.total_iops_sec && def->blkdeviotune.write_iops_sec)) {
+                    virDomainReportError(VIR_ERR_XML_ERROR,
+                                         _("total and read/write iops_sec cannot be set at the same time"));
+                    goto error;
+                }
             } else if (xmlStrEqual(cur->name, BAD_CAST "readonly")) {
                 def->readonly = 1;
             } else if (xmlStrEqual(cur->name, BAD_CAST "shareable")) {
@@ -6003,7 +6060,7 @@ virDomainDeviceDefPtr virDomainDeviceDefParse(virCapsPtr caps,
     if (xmlStrEqual(node->name, BAD_CAST "disk")) {
         dev->type = VIR_DOMAIN_DEVICE_DISK;
         if (!(dev->data.disk = virDomainDiskDefParseXML(caps, node,
-                                                        NULL, flags)))
+                                                        NULL, flags, NULL)))
             goto error;
     } else if (xmlStrEqual(node->name, BAD_CAST "lease")) {
         dev->type = VIR_DOMAIN_DEVICE_LEASE;
@@ -7076,7 +7133,8 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
         virDomainDiskDefPtr disk = virDomainDiskDefParseXML(caps,
                                                             nodes[i],
                                                             bootMap,
-                                                            flags);
+                                                            flags,
+                                                            ctxt);
         if (!disk)
             goto error;
 
@@ -9511,6 +9569,43 @@ virDomainDiskDefFormat(virBufferPtr buf,
     virBufferAsprintf(buf, "      <target dev='%s' bus='%s'/>\n",
                       def->dst, bus);
 
+    /*disk I/O throttling*/
+    if (def->blkdeviotune.mark) {
+        virBufferAddLit(buf, "      <iotune>\n");
+        if (def->blkdeviotune.total_bytes_sec) {
+            virBufferAsprintf(buf, "        <total_bytes_sec>%llu</total_bytes_sec>\n",
+                              def->blkdeviotune.total_bytes_sec);
+        }
+
+        if (def->blkdeviotune.read_bytes_sec) {
+            virBufferAsprintf(buf, "        <read_bytes_sec>%llu</read_bytes_sec>\n",
+                              def->blkdeviotune.read_bytes_sec);
+
+        }
+
+        if (def->blkdeviotune.write_bytes_sec) {
+            virBufferAsprintf(buf, "        <write_bytes_sec>%llu</write_bytes_sec>\n",
+                              def->blkdeviotune.write_bytes_sec);
+        }
+
+        if (def->blkdeviotune.total_iops_sec) {
+            virBufferAsprintf(buf, "        <total_iops_sec>%llu</total_iops_sec>\n",
+                              def->blkdeviotune.total_iops_sec);
+        }
+
+        if (def->blkdeviotune.read_iops_sec) {
+            virBufferAsprintf(buf, "        <read_iops_sec>%llu</read_iops_sec>",
+                              def->blkdeviotune.read_iops_sec);
+        }
+
+        if (def->blkdeviotune.write_iops_sec) {
+            virBufferAsprintf(buf, "        <write_iops_sec>%llu</write_iops_sec>",
+                              def->blkdeviotune.write_iops_sec);
+        }
+
+        virBufferAddLit(buf, "      </iotune>\n");
+    }
+
     if (def->bootIndex)
         virBufferAsprintf(buf, "      <boot order='%d'/>\n", def->bootIndex);
     if (def->readonly)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index a3cb834..d95e239 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -333,6 +333,18 @@ struct _virDomainDiskDef {
     } auth;
     char *driverName;
     char *driverType;
+
+    /*disk I/O throttling*/
+    struct {
+        unsigned long long total_bytes_sec;
+        unsigned long long read_bytes_sec;
+        unsigned long long write_bytes_sec;
+        unsigned long long total_iops_sec;
+        unsigned long long read_iops_sec;
+        unsigned long long write_iops_sec;
+        unsigned int mark;
+    } blkdeviotune;
+
     char *serial;
     int cachemode;
     int error_policy;  /* enum virDomainDiskErrorPolicy */
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 2fbf691..91c6508 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1690,6 +1690,39 @@ qemuBuildDriveStr(virConnectPtr conn ATTRIBUTE_UNUSED,
         }
     }
 
+    /*block I/O throttling*/
+    if (disk->blkdeviotune.mark) {
+        if (disk->blkdeviotune.total_bytes_sec) {
+            virBufferAsprintf(&opt, ",bps=%llu",
+                              disk->blkdeviotune.total_bytes_sec);
+        }
+
+        if (disk->blkdeviotune.read_bytes_sec) {
+            virBufferAsprintf(&opt, ",bps_rd=%llu",
+                              disk->blkdeviotune.read_bytes_sec);
+        }
+
+        if (disk->blkdeviotune.write_bytes_sec) {
+            virBufferAsprintf(&opt, ",bps_wr=%llu",
+                              disk->blkdeviotune.write_bytes_sec);
+        }
+
+        if (disk->blkdeviotune.total_iops_sec) {
+            virBufferAsprintf(&opt, ",iops=%llu",
+                              disk->blkdeviotune.total_iops_sec);
+        }
+
+        if (disk->blkdeviotune.read_iops_sec) {
+            virBufferAsprintf(&opt, ",iops_rd=%llu",
+                              disk->blkdeviotune.read_iops_sec);
+        }
+
+        if (disk->blkdeviotune.write_iops_sec) {
+            virBufferAsprintf(&opt, ",iops_wr=%llu",
+                              disk->blkdeviotune.write_iops_sec);
+        }
+    }
+
     if (virBufferError(&opt)) {
         virReportOOMError();
         goto error;
diff --git a/src/util/xml.h b/src/util/xml.h
index c492063..5742f19 100644
--- a/src/util/xml.h
+++ b/src/util/xml.h
@@ -50,6 +50,8 @@ xmlNodePtr          virXPathNode(const char *xpath,
 int              virXPathNodeSet(const char *xpath,
                                  xmlXPathContextPtr ctxt,
                                  xmlNodePtr **list);
+int     virXMLStringToULongLong (const char *stringval,
+                                 unsigned long long *value);
 char *          virXMLPropString(xmlNodePtr node,
                                  const char *name);
 
-- 
1.7.1




More information about the libvir-list mailing list