Enable block I/O throttle for per-disk in XML.
Signed-off-by: Lei Li <lilei(a)linux.vnet.ibm.com>
Signed-off-by: Zhi Yong Wu <wuzhy(a)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