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;