diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 42df928a30..5d8f66957a 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 @@
Only QEMU driver support since 0.9.4, LXC since
0.9.10
+
+
emulator_period
+
+ The optional emulator_period
element specifies the enforcement
+ interval(unit: microseconds). Within emulator_period
, emulator
+ threads(those excluding vcpus) of the domain will not be allowed to consume
+ more than emulator_quota
worth of runtime. The value should be
+ in range [1000, 1000000]. A period with value 0 means no value.
+ Only QEMU driver support since 0.10.0
+
+ emulator_quota
+
+ The optional emulator_quota
element specifies the maximum
+ allowed bandwidth(unit: microseconds) for domain's emulator threads(those
+ excluding vcpus). A domain with emulator_quota
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.
+ Only QEMU driver support since 0.10.0
+
+
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index f4005c51e2..145caf78d8 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -581,6 +581,16 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 9e97301374..724220576a 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -8344,6 +8344,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;
}
@@ -13102,7 +13110,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, " \n");
if (def->cputune.shares)
@@ -13114,6 +13123,17 @@ virDomainDefFormatInternal(virDomainDefPtr def,
if (def->cputune.quota)
virBufferAsprintf(buf, " %lld\n",
def->cputune.quota);
+
+ if (def->cputune.emulator_period)
+ virBufferAsprintf(buf, " %llu"
+ "\n",
+ def->cputune.emulator_period);
+
+ if (def->cputune.emulator_quota)
+ virBufferAsprintf(buf, " %lld"
+ "\n",
+ def->cputune.emulator_quota);
+
if (def->cputune.vcpupin) {
for (i = 0; i < def->cputune.nvcpupin; i++) {
virBufferAsprintf(buf, " 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, " \n");
if (def->numatune.memory.nodemask ||
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 5a02323ea7..0c3824ec7f 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1614,6 +1614,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 2fb29b5f5f..2237d119e6 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;