On Mon, Jul 25, 2011 at 01:37:14PM +0800, Wen Congyang wrote:
The cpu bandwidth is applied at the vcpu group level. We should apply
it
at the vm group level too, because the vm may do heavy I/O, and it will affect
the other vm.
We apply cpu bandwidth at the vcpu and the vm group level, so we must ensure
that max(child_quota) <= parent_quota when we modify cpu bandwidth.
---
src/qemu/qemu_cgroup.c | 38 ++++++++++-------
src/qemu/qemu_driver.c | 103 ++++++++++++++++++++++++++++++++++++-----------
2 files changed, 101 insertions(+), 40 deletions(-)
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index d6e4cbc..2a10bd2 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -435,6 +435,7 @@ int qemuSetupCgroupForVcpu(struct qemud_driver *driver,
virDomainObjPtr vm)
unsigned int i;
unsigned long long period = vm->def->cputune.period;
long long quota = vm->def->cputune.quota;
+ long long vm_quota = 0;
if (driver->cgroup == NULL)
return 0; /* Not supported, so claim success */
@@ -447,26 +448,31 @@ int qemuSetupCgroupForVcpu(struct qemud_driver *driver,
virDomainObjPtr vm)
goto cleanup;
}
+ /* Set cpu bandwidth for the vm */
+ if (period || quota) {
+ if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) {
+ /* Ensure that we can multiply by vcpus without overflowing. */
+ if (quota > LLONG_MAX / vm->def->vcpus) {
+ virReportSystemError(EINVAL,
+ _("%s"),
+ "Unable to set cpu bandwidth quota");
+ goto cleanup;
+ }
+
+ if (quota > 0)
+ vm_quota = quota * vm->def->vcpus;
+ else
+ vm_quota = quota;
+ if (qemuSetupCgroupVcpuBW(cgroup, period, vm_quota) < 0)
+ goto cleanup;
+ }
+ }
+
if (priv->nvcpupids == 0 || priv->vcpupids[0] == vm->pid) {
/* If we does not know VCPU<->PID mapping or all vcpu runs in the same
* thread, we cannot control each vcpu.
*/
- if (period || quota) {
- if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) {
- /* Ensure that we can multiply by vcpus without overflowing. */
- if (quota > LLONG_MAX / vm->def->vcpus) {
- virReportSystemError(EINVAL,
- _("%s"),
- "Unable to set cpu bandwidth
quota");
- goto cleanup;
- }
-
- if (quota > 0)
- quota *= vm->def->vcpus;
- if (qemuSetupCgroupVcpuBW(cgroup, period, quota) < 0)
- goto cleanup;
- }
- }
+ virCgroupFree(&cgroup);
return 0;
}
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 5df58b1..52e5d69 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -6051,43 +6051,98 @@ qemuSetVcpusBWLive(virDomainObjPtr vm, virCgroupPtr cgroup,
qemuDomainObjPrivatePtr priv = vm->privateData;
virCgroupPtr cgroup_vcpu = NULL;
int rc;
+ long long vm_quota = 0;
+ long long old_quota = 0;
+ unsigned long long old_period = 0;
if (period == 0 && quota == 0)
return 0;
- if (priv->nvcpupids == 0 || priv->vcpupids[0] == vm->pid) {
- /* If we does not know VCPU<->PID mapping or all vcpu runs in the same
- * thread, we cannot control each vcpu.
- */
- /* Ensure that we can multiply by vcpus without overflowing. */
- if (quota > LLONG_MAX / vm->def->vcpus) {
- virReportSystemError(EINVAL,
- _("%s"),
- "Unable to set cpu bandwidth quota");
- goto cleanup;
- }
+ /* Ensure that we can multiply by vcpus without overflowing. */
+ if (quota > LLONG_MAX / vm->def->vcpus) {
+ virReportSystemError(EINVAL,
+ _("%s"),
+ "Unable to set cpu bandwidth quota");
+ goto cleanup;
+ }
+
+ if (quota > 0)
+ vm_quota = quota * vm->def->vcpus;
+ else
+ vm_quota = quota;
- if (quota > 0)
- quota *= vm->def->vcpus;
- return qemuSetupCgroupVcpuBW(cgroup, period, quota);
+ rc = virCgroupGetCpuCfsQuota(cgroup, &old_quota);
+ if (rc < 0) {
+ virReportSystemError(-rc, "%s",
+ _("unable to get cpu bandwidth tunable"));
+ goto cleanup;
}
- for (i = 0; i < priv->nvcpupids; i++) {
- rc = virCgroupForVcpu(cgroup, i, &cgroup_vcpu, 0);
- if (rc < 0) {
- virReportSystemError(-rc,
- _("Unable to find vcpu cgroup for %s(vcpu:"
- " %d)"),
- vm->def->name, i);
- goto cleanup;
+ rc = virCgroupGetCpuCfsPeriod(cgroup, &old_period);
+ if (rc < 0) {
+ virReportSystemError(-rc, "%s",
+ _("unable to get cpu bandwidth period
tunable"));
+ goto cleanup;
+ }
+
+ /*
+ * If quota will be changed to a small value, we should modify vcpu's quota
+ * first. Otherwise, we should modify vm's quota first.
+ *
+ * If period will be changed to a small value, we should modify vm's period
+ * first. Otherwise, we should modify vcpu's period first.
+ *
+ * If both quota and period will be changed to a big/small value, we cannot
+ * modify period and quota together.
+ */
+ if ((quota != 0) && (period != 0)) {
+ if (((quota > old_quota) && (period > old_period)) ||
+ ((quota < old_quota) && (period < old_period))) {
+ /* modify period */
+ if (qemuSetVcpusBWLive(vm, cgroup, period, 0) < 0)
+ goto cleanup;
+
+ /* modify quota */
+ if (qemuSetVcpusBWLive(vm, cgroup, 0, quota) < 0)
+ goto cleanup;
+ return 0;
}
+ }
- if (qemuSetupCgroupVcpuBW(cgroup_vcpu, period, quota) < 0)
+ if (((vm_quota != 0) && (vm_quota > old_quota)) ||
+ ((period != 0) && (period < old_period)))
+ /* Set cpu bandwidth for the vm */
+ if (qemuSetupCgroupVcpuBW(cgroup, period, vm_quota) < 0)
goto cleanup;
- virCgroupFree(&cgroup_vcpu);
+ /* If we does not know VCPU<->PID mapping or all vcpu runs in the same
+ * thread, we cannot control each vcpu. So we only modify cpu bandwidth
+ * when each vcpu has a separated thread.
+ */
+ if (priv->nvcpupids != 0 && priv->vcpupids[0] != vm->pid) {
+ for (i = 0; i < priv->nvcpupids; i++) {
+ rc = virCgroupForVcpu(cgroup, i, &cgroup_vcpu, 0);
+ if (rc < 0) {
+ virReportSystemError(-rc,
+ _("Unable to find vcpu cgroup for
%s(vcpu:"
+ " %d)"),
+ vm->def->name, i);
+ goto cleanup;
+ }
+
+ if (qemuSetupCgroupVcpuBW(cgroup_vcpu, period, quota) < 0)
+ goto cleanup;
+
+ virCgroupFree(&cgroup_vcpu);
+ }
}
+ if (((vm_quota != 0) && (vm_quota <= old_quota)) ||
+ ((period != 0) && (period >= old_period)))
+ /* Set cpu bandwidth for the vm */
+ if (qemuSetupCgroupVcpuBW(cgroup, period, vm_quota) < 0)
+ goto cleanup;
+
return 0;
cleanup:
I looked at it yesterday but while looking correct I was hoping
someone with more interest on that thread would comment/ACK it.
ACK,
I just tagged libvirt-0.9.4-rc1, so that won't make it but it will be
in rc2 and final which is the important point :-)
Daniel
--
Daniel Veillard | libxml Gnome XML XSLT toolkit
http://xmlsoft.org/
daniel(a)veillard.com | Rpmfind RPM search engine
http://rpmfind.net/
http://veillard.com/ | virtualization library
http://libvirt.org/