This patch introduces support of setting emulator's period and
quota to limit cpu bandwidth when the vm starts. Also updates
XML Schema for new entries and docs.
---
docs/formatdomain.html.in | 24 ++++++++++++++++++++++++
docs/schemas/domaincommon.rng | 10 ++++++++++
src/conf/domain_conf.c | 25 +++++++++++++++++++++++--
src/conf/domain_conf.h | 2 ++
src/qemu/qemu_cgroup.c | 11 ++++++++++-
5 files changed, 69 insertions(+), 3 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 81ec2cd..6142f4b 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -388,6 +388,8 @@
<shares>2048</shares>
<period>1000000</period>
<quota>-1</quota>
+ <emulator_period>1000000</period>
+ <emulator_quota>-1</quota>
</cputune>
...
</domain>
@@ -451,6 +453,28 @@
<span class="since">Only QEMU driver support since 0.9.4, LXC
since
0.9.10</span>
</dd>
+
+ <dt><code>emulator_period</code></dt>
+ <dd>
+ The optional <code>emulator_period</code> element specifies the
enforcement
+ interval(unit: microseconds). Within <code>emulator_period</code>,
emulator
+ threads(those excluding vcpus) of the domain will not be allowed to consume
+ more than <code>emulator_quota</code> worth of runtime. The value
should be
+ in range [1000, 1000000]. A period with value 0 means no value.
+ <span class="since">Only QEMU driver support since
0.10.0</span>
+ </dd>
+ <dt><code>emulator_quota</code></dt>
+ <dd>
+ The optional <code>emulator_quota</code> element specifies the
maximum
+ allowed bandwidth(unit: microseconds) for domain's emulator threads(those
+ excluding vcpus). A domain with <code>emulator_quota</code> as any
negative
+ value indicates that the domain has infinite bandwidth for emulator threads
+ (those excluding vcpus), which means that it is not bandwidth controlled.
+ The value should be in range [1000, 18446744073709551] or less than 0. A
+ quota with value 0 means no value.
+ <span class="since">Only QEMU driver support since
0.10.0</span>
+ </dd>
+
</dl>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index b02ad96..7aa6e47 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -581,6 +581,16 @@
<ref name="cpuquota"/>
</element>
</optional>
+ <optional>
+ <element name="emulator_period">
+ <ref name="cpuperiod"/>
+ </element>
+ </optional>
+ <optional>
+ <element name="emulator_quota">
+ <ref name="cpuquota"/>
+ </element>
+ </optional>
<zeroOrMore>
<element name="vcpupin">
<attribute name="vcpu">
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index dab9c5d..7bb07b4 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -8297,6 +8297,14 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
&def->cputune.quota) < 0)
def->cputune.quota = 0;
+ if (virXPathULongLong("string(./cputune/emulator_period[1])", ctxt,
+ &def->cputune.emulator_period) < 0)
+ def->cputune.emulator_period = 0;
+
+ if (virXPathLongLong("string(./cputune/emulator_quota[1])", ctxt,
+ &def->cputune.emulator_quota) < 0)
+ def->cputune.emulator_quota = 0;
+
if ((n = virXPathNodeSet("./cputune/vcpupin", ctxt, &nodes)) < 0) {
goto error;
}
@@ -13030,7 +13038,8 @@ virDomainDefFormatInternal(virDomainDefPtr def,
if (def->cputune.shares || def->cputune.vcpupin ||
def->cputune.period || def->cputune.quota ||
- def->cputune.emulatorpin)
+ def->cputune.emulatorpin ||
+ def->cputune.emulator_period || def->cputune.emulator_quota)
virBufferAddLit(buf, " <cputune>\n");
if (def->cputune.shares)
@@ -13042,6 +13051,17 @@ virDomainDefFormatInternal(virDomainDefPtr def,
if (def->cputune.quota)
virBufferAsprintf(buf, " <quota>%lld</quota>\n",
def->cputune.quota);
+
+ if (def->cputune.emulator_period)
+ virBufferAsprintf(buf, " <emulator_period>%llu"
+ "</emulator_period>\n",
+ def->cputune.emulator_period);
+
+ if (def->cputune.emulator_quota)
+ virBufferAsprintf(buf, " <emulator_quota>%lld"
+ "</emulator_quota>\n",
+ def->cputune.emulator_quota);
+
if (def->cputune.vcpupin) {
for (i = 0; i < def->cputune.nvcpupin; i++) {
virBufferAsprintf(buf, " <vcpupin vcpu='%u' ",
@@ -13080,7 +13100,8 @@ virDomainDefFormatInternal(virDomainDefPtr def,
if (def->cputune.shares || def->cputune.vcpupin ||
def->cputune.period || def->cputune.quota ||
- def->cputune.emulatorpin)
+ def->cputune.emulatorpin ||
+ def->cputune.emulator_period || def->cputune.emulator_quota)
virBufferAddLit(buf, " </cputune>\n");
if (def->numatune.memory.nodemask ||
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index b6bf5a8..089d9bc 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1598,6 +1598,8 @@ struct _virDomainDef {
unsigned long shares;
unsigned long long period;
long long quota;
+ unsigned long long emulator_period;
+ long long emulator_quota;
int nvcpupin;
virDomainVcpuPinDefPtr *vcpupin;
virDomainVcpuPinDefPtr emulatorpin;
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index 2fb29b5..2237d11 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -564,7 +564,7 @@ int qemuSetupCgroupForVcpu(struct qemud_driver *driver,
virDomainObjPtr vm)
}
if (priv->nvcpupids == 0 || priv->vcpupids[0] == vm->pid) {
- /* If we does not know VCPU<->PID mapping or all vcpus run in the same
+ /* If we don't know VCPU<->PID mapping or all vcpu runs in the same
* thread, we cannot control each vcpu.
*/
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -631,6 +631,8 @@ int qemuSetupCgroupForEmulator(struct qemud_driver *driver,
virCgroupPtr cgroup = NULL;
virCgroupPtr cgroup_emulator = NULL;
virDomainDefPtr def = vm->def;
+ unsigned long long period = vm->def->cputune.emulator_period;
+ long long quota = vm->def->cputune.emulator_quota;
int rc, i;
if (driver->cgroup == NULL)
@@ -672,6 +674,13 @@ int qemuSetupCgroupForEmulator(struct qemud_driver *driver,
qemuSetupCgroupEmulatorPin(cgroup_emulator, def->cputune.emulatorpin) < 0)
goto cleanup;
+ if (period || quota) {
+ if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) {
+ if (qemuSetupCgroupVcpuBW(cgroup_emulator, period, quota) < 0)
+ goto cleanup;
+ }
+ }
+
virCgroupFree(&cgroup_emulator);
virCgroupFree(&cgroup);
return 0;
--
1.7.10.2