From b65dafa812abc4f5c3b8a035b96a80785ac40ee1 Mon Sep 17 00:00:00 2001 From: Hu Tao Date: Tue, 21 Aug 2012 17:18:42 +0800 Subject: [PATCH] qemu: introduce period/quota tuning for emulator 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 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;