This looks good to me. On Thu, Nov 10, 2011 at 04:32:54AM +0800, Lei HH Li wrote: > Enable block I/O throttle for per-disk in XML. > > Signed-off-by: Zhi Yong Wu <wuzhy@xxxxxxxxxxxxxxxxxx> > Signed-off-by: Lei Li <lilei@xxxxxxxxxxxxxxxxxx> > --- > 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..564914e 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, > + _("bps and bps_rd/bps_wr 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, > + _("iops and iops_rd/iops_wr 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 11ebb69..3a8575b 100644 > --- a/src/qemu/qemu_command.c > +++ b/src/qemu/qemu_command.c > @@ -1715,6 +1715,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 > -- Adam Litke <agl@xxxxxxxxxx> IBM Linux Technology Center -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list