提交 6df7ccb1 编写于 作者: L Lei Li 提交者: Eric Blake

Support block I/O throttle in XML

Enable block I/O throttle for per-disk in XML, as the first
per-disk IO tuning parameter.
Signed-off-by: NLei Li <lilei@linux.vnet.ibm.com>
Signed-off-by: NZhi Yong Wu <wuzhy@linux.vnet.ibm.com>
Signed-off-by: NEric Blake <eblake@redhat.com>
上级 115a2a3f
...@@ -536,7 +536,11 @@ ...@@ -536,7 +536,11 @@
single host block device, if they are backed by files within single host block device, if they are backed by files within
the same host file system, which is why this tuning parameter the same host file system, which is why this tuning parameter
is at the global domain level rather than associated with each is at the global domain level rather than associated with each
guest disk device. Each <code>device</code> element has two guest disk device (contrast this to
the <a href="#elementsDisks"><code>&lt;iotune&gt;</code></a>
element which can apply to an
individual <code>&lt;disk&gt;</code>).
Each <code>device</code> element has two
mandatory sub-elements, <code>path</code> describing the mandatory sub-elements, <code>path</code> describing the
absolute path of the device, and <code>weight</code> giving absolute path of the device, and <code>weight</code> giving
the relative weight of that device, in the range [100, the relative weight of that device, in the range [100,
...@@ -945,6 +949,11 @@ ...@@ -945,6 +949,11 @@
&lt;driver name="tap" type="aio" cache="default"/&gt; &lt;driver name="tap" type="aio" cache="default"/&gt;
&lt;source file='/var/lib/xen/images/fv0'/ startupPolicy='optional'&gt; &lt;source file='/var/lib/xen/images/fv0'/ startupPolicy='optional'&gt;
&lt;target dev='hda' bus='ide'/&gt; &lt;target dev='hda' bus='ide'/&gt;
&lt;iotune&gt;
&lt;total_bytes_sec&gt;10000000&lt;/total_bytes_sec&gt;
&lt;read_iops_sec&gt;400000&lt;/read_iops_sec&gt;
&lt;write_iops_sec&gt;100000&lt;/write_iops_sec&gt;
&lt;/iotune&gt;
&lt;boot order='2'/&gt; &lt;boot order='2'/&gt;
&lt;encryption type='...'&gt; &lt;encryption type='...'&gt;
... ...
...@@ -1062,6 +1071,40 @@ ...@@ -1062,6 +1071,40 @@
<span class="since">Since 0.0.3; <code>bus</code> attribute since 0.4.3; <span class="since">Since 0.0.3; <code>bus</code> attribute since 0.4.3;
"usb" attribute value since after 0.4.4; "sata" attribute value since "usb" attribute value since after 0.4.4; "sata" attribute value since
0.9.7</span></dd> 0.9.7</span></dd>
<dt><code>iotune</code></dt>
<dd>The optional <code>iotune</code> element provides the
ability to provide additional per-device I/O tuning, with
values that can vary for each device (contrast this to
the <a href="#elementsBlockTuning"><code>&lt;blkiotune&gt;</code></a>
element, which applies globally to the domain). Currently,
the only tuning available is Block I/O throttling for qemu.
This element has optional sub-elements; any sub-element not
specified or given with a value of 0 implies no
limit. <span class="since">Since 0.9.8</span>
<dl>
<dt><code>total_bytes_sec</code></dt>
<dd>The optional <code>total_bytes_sec</code> element is the
total throughput limit in bytes per second. This cannot
appear with <code>read_bytes_sec</code>
or <code>write_bytes_sec</code>.</dd>
<dt><code>read_bytes_sec</code></dt>
<dd>The optional <code>read_bytes_sec</code> element is the
read throughput limit in bytes per second.</dd>
<dt><code>write_bytes_sec</code></dt>
<dd>The optional <code>write_bytes_sec</code> element is the
write throughput limit in bytes per second.</dd>
<dt><code>total_iops_sec</code></dt>
<dd>The optional <code>total_iops_sec</code> element is the
total I/O operations per second. This cannot
appear with <code>read_iops_sec</code>
or <code>write_iops_sec</code>.</dd>
<dt><code>read_iops_sec</code></dt>
<dd>The optional <code>read_iops_sec</code> element is the
read I/O operations per second.</dd>
<dt><code>write_iops_sec</code></dt>
<dd>The optional <code>write_iops_sec</code> element is the
write I/O operations per second.</dd>
</dl>
<dt><code>driver</code></dt> <dt><code>driver</code></dt>
<dd> <dd>
The optional driver element allows specifying further details The optional driver element allows specifying further details
......
...@@ -618,42 +618,47 @@ ...@@ -618,42 +618,47 @@
</element> </element>
</define> </define>
<define name="diskspec"> <define name="diskspec">
<optional> <interleave>
<ref name="driver"/> <optional>
</optional> <ref name="driver"/>
<optional> </optional>
<ref name="diskAuth"/> <optional>
</optional> <ref name="diskAuth"/>
<ref name="target"/> </optional>
<optional> <ref name="target"/>
<ref name="deviceBoot"/> <optional>
</optional> <ref name="deviceBoot"/>
<optional> </optional>
<element name="readonly"> <optional>
<empty/> <element name="readonly">
</element> <empty/>
</optional> </element>
<optional> </optional>
<element name="shareable"> <optional>
<empty/> <element name="shareable">
</element> <empty/>
</optional> </element>
<optional> </optional>
<element name="transient"> <optional>
<empty/> <element name="transient">
</element> <empty/>
</optional> </element>
<optional> </optional>
<element name="serial"> <optional>
<ref name="diskSerial"/> <element name="serial">
</element> <ref name="diskSerial"/>
</optional> </element>
<optional> </optional>
<ref name="encryption"/> <optional>
</optional> <ref name="encryption"/>
<optional> </optional>
<ref name="address"/> <optional>
</optional> <ref name="diskIoTune"/>
</optional>
<optional>
<ref name="address"/>
</optional>
</interleave>
</define> </define>
<define name="snapshot"> <define name="snapshot">
<attribute name="snapshot"> <attribute name="snapshot">
...@@ -2615,6 +2620,51 @@ ...@@ -2615,6 +2620,51 @@
</element> </element>
</define> </define>
<define name='diskIoTune'>
<element name="iotune">
<interleave>
<choice>
<element name="total_bytes_sec">
<data type="unsignedLong"/>
</element>
<group>
<interleave>
<optional>
<element name="read_bytes_sec">
<data type="unsignedLong"/>
</element>
</optional>
<optional>
<element name="write_bytes_sec">
<data type="unsignedLong"/>
</element>
</optional>
</interleave>
</group>
</choice>
<choice>
<element name="total_iops_sec">
<data type="unsignedLong"/>
</element>
<group>
<interleave>
<optional>
<element name="read_iops_sec">
<data type="unsignedLong"/>
</element>
</optional>
<optional>
<element name="write_iops_sec">
<data type="unsignedLong"/>
</element>
</optional>
</interleave>
</group>
</choice>
</interleave>
</element>
</define>
<!-- <!--
Optional hypervisor extensions in their own namespace: Optional hypervisor extensions in their own namespace:
QEmu QEmu
......
...@@ -2507,11 +2507,13 @@ cleanup: ...@@ -2507,11 +2507,13 @@ cleanup:
static virDomainDiskDefPtr static virDomainDiskDefPtr
virDomainDiskDefParseXML(virCapsPtr caps, virDomainDiskDefParseXML(virCapsPtr caps,
xmlNodePtr node, xmlNodePtr node,
xmlXPathContextPtr ctxt,
virBitmapPtr bootMap, virBitmapPtr bootMap,
unsigned int flags) unsigned int flags)
{ {
virDomainDiskDefPtr def; virDomainDiskDefPtr def;
xmlNodePtr cur, child; xmlNodePtr cur, child;
xmlNodePtr save_ctxt = ctxt->node;
char *type = NULL; char *type = NULL;
char *device = NULL; char *device = NULL;
char *snapshot = NULL; char *snapshot = NULL;
...@@ -2543,6 +2545,8 @@ virDomainDiskDefParseXML(virCapsPtr caps, ...@@ -2543,6 +2545,8 @@ virDomainDiskDefParseXML(virCapsPtr caps,
return NULL; return NULL;
} }
ctxt->node = node;
type = virXMLPropString(node, "type"); type = virXMLPropString(node, "type");
if (type) { if (type) {
if ((def->type = virDomainDiskTypeFromString(type)) < 0) { if ((def->type = virDomainDiskTypeFromString(type)) < 0) {
...@@ -2707,6 +2711,62 @@ virDomainDiskDefParseXML(virCapsPtr caps, ...@@ -2707,6 +2711,62 @@ virDomainDiskDefParseXML(virCapsPtr caps,
} }
child = child->next; child = child->next;
} }
} else if (xmlStrEqual(cur->name, BAD_CAST "iotune")) {
if (virXPathULongLong("string(./iotune/total_bytes_sec)",
ctxt,
&def->blkdeviotune.total_bytes_sec) < 0) {
def->blkdeviotune.total_bytes_sec = 0;
}
if (virXPathULongLong("string(./iotune/read_bytes_sec)",
ctxt,
&def->blkdeviotune.read_bytes_sec) < 0) {
def->blkdeviotune.read_bytes_sec = 0;
}
if (virXPathULongLong("string(./iotune/write_bytes_sec)",
ctxt,
&def->blkdeviotune.write_bytes_sec) < 0) {
def->blkdeviotune.write_bytes_sec = 0;
}
if (virXPathULongLong("string(./iotune/total_iops_sec)",
ctxt,
&def->blkdeviotune.total_iops_sec) < 0) {
def->blkdeviotune.total_iops_sec = 0;
}
if (virXPathULongLong("string(./iotune/read_iops_sec)",
ctxt,
&def->blkdeviotune.read_iops_sec) < 0) {
def->blkdeviotune.read_iops_sec = 0;
}
if (virXPathULongLong("string(./iotune/write_iops_sec)",
ctxt,
&def->blkdeviotune.write_iops_sec) < 0) {
def->blkdeviotune.write_iops_sec = 0;
}
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")) { } else if (xmlStrEqual(cur->name, BAD_CAST "readonly")) {
def->readonly = 1; def->readonly = 1;
} else if (xmlStrEqual(cur->name, BAD_CAST "shareable")) { } else if (xmlStrEqual(cur->name, BAD_CAST "shareable")) {
...@@ -3001,6 +3061,7 @@ cleanup: ...@@ -3001,6 +3061,7 @@ cleanup:
virStorageEncryptionFree(encryption); virStorageEncryptionFree(encryption);
VIR_FREE(startupPolicy); VIR_FREE(startupPolicy);
ctxt->node = save_ctxt;
return def; return def;
no_memory: no_memory:
...@@ -6191,7 +6252,7 @@ virDomainDeviceDefPtr virDomainDeviceDefParse(virCapsPtr caps, ...@@ -6191,7 +6252,7 @@ virDomainDeviceDefPtr virDomainDeviceDefParse(virCapsPtr caps,
if (xmlStrEqual(node->name, BAD_CAST "disk")) { if (xmlStrEqual(node->name, BAD_CAST "disk")) {
dev->type = VIR_DOMAIN_DEVICE_DISK; dev->type = VIR_DOMAIN_DEVICE_DISK;
if (!(dev->data.disk = virDomainDiskDefParseXML(caps, node, if (!(dev->data.disk = virDomainDiskDefParseXML(caps, node, ctxt,
NULL, flags))) NULL, flags)))
goto error; goto error;
} else if (xmlStrEqual(node->name, BAD_CAST "lease")) { } else if (xmlStrEqual(node->name, BAD_CAST "lease")) {
...@@ -7277,6 +7338,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, ...@@ -7277,6 +7338,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
for (i = 0 ; i < n ; i++) { for (i = 0 ; i < n ; i++) {
virDomainDiskDefPtr disk = virDomainDiskDefParseXML(caps, virDomainDiskDefPtr disk = virDomainDiskDefParseXML(caps,
nodes[i], nodes[i],
ctxt,
bootMap, bootMap,
flags); flags);
if (!disk) if (!disk)
...@@ -9733,6 +9795,48 @@ virDomainDiskDefFormat(virBufferPtr buf, ...@@ -9733,6 +9795,48 @@ virDomainDiskDefFormat(virBufferPtr buf,
virBufferAsprintf(buf, " <target dev='%s' bus='%s'/>\n", virBufferAsprintf(buf, " <target dev='%s' bus='%s'/>\n",
def->dst, bus); def->dst, bus);
/*disk I/O throttling*/
if (def->blkdeviotune.total_bytes_sec ||
def->blkdeviotune.read_bytes_sec ||
def->blkdeviotune.write_bytes_sec ||
def->blkdeviotune.total_iops_sec ||
def->blkdeviotune.read_iops_sec ||
def->blkdeviotune.write_iops_sec) {
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) if (def->bootIndex)
virBufferAsprintf(buf, " <boot order='%d'/>\n", def->bootIndex); virBufferAsprintf(buf, " <boot order='%d'/>\n", def->bootIndex);
if (def->readonly) if (def->readonly)
......
...@@ -310,6 +310,17 @@ enum virDomainDiskSecretType { ...@@ -310,6 +310,17 @@ enum virDomainDiskSecretType {
VIR_DOMAIN_DISK_SECRET_TYPE_LAST VIR_DOMAIN_DISK_SECRET_TYPE_LAST
}; };
typedef struct _virDomainBlockIoTuneInfo virDomainBlockIoTuneInfo;
struct _virDomainBlockIoTuneInfo {
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;
};
typedef virDomainBlockIoTuneInfo *virDomainBlockIoTuneInfoPtr;
/* Stores the virtual disk configuration */ /* Stores the virtual disk configuration */
typedef struct _virDomainDiskDef virDomainDiskDef; typedef struct _virDomainDiskDef virDomainDiskDef;
typedef virDomainDiskDef *virDomainDiskDefPtr; typedef virDomainDiskDef *virDomainDiskDefPtr;
...@@ -332,6 +343,9 @@ struct _virDomainDiskDef { ...@@ -332,6 +343,9 @@ struct _virDomainDiskDef {
} auth; } auth;
char *driverName; char *driverName;
char *driverType; char *driverType;
virDomainBlockIoTuneInfo blkdeviotune;
char *serial; char *serial;
int cachemode; int cachemode;
int error_policy; /* enum virDomainDiskErrorPolicy */ int error_policy; /* enum virDomainDiskErrorPolicy */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册