set hypervisor's period and quota when the vm starts. It will affect to set
vm's period and quota: donot set vm's period and quota if we limit hypevisor
thread's bandwidth(hypervisor_quota > 0).
---
src/conf/domain_conf.c | 25 ++++++++++++++-
src/conf/domain_conf.h | 2 +
src/qemu/qemu_cgroup.c | 37 ++++++++++++++++-------
src/qemu/qemu_driver.c | 75 ++++++++++++++++++++++++++++++------------------
4 files changed, 98 insertions(+), 41 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 5ab052a..28a6436 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -7931,6 +7931,14 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
&def->cputune.quota) < 0)
def->cputune.quota = 0;
+ if (virXPathULongLong("string(./cputune/hypervisor_period[1])", ctxt,
+ &def->cputune.hypervisor_period) < 0)
+ def->cputune.hypervisor_period = 0;
+
+ if (virXPathLongLong("string(./cputune/hypervisor_quota[1])", ctxt,
+ &def->cputune.hypervisor_quota) < 0)
+ def->cputune.hypervisor_quota = 0;
+
if ((n = virXPathNodeSet("./cputune/vcpupin", ctxt, &nodes)) < 0) {
goto error;
}
@@ -12406,7 +12414,8 @@ virDomainDefFormatInternal(virDomainDefPtr def,
virBufferAsprintf(buf, ">%u</vcpu>\n", def->maxvcpus);
if (def->cputune.shares || def->cputune.vcpupin ||
- def->cputune.period || def->cputune.quota)
+ def->cputune.period || def->cputune.quota ||
+ def->cputune.hypervisor_period || def->cputune.hypervisor_quota)
virBufferAddLit(buf, " <cputune>\n");
if (def->cputune.shares)
@@ -12418,6 +12427,17 @@ virDomainDefFormatInternal(virDomainDefPtr def,
if (def->cputune.quota)
virBufferAsprintf(buf, " <quota>%lld</quota>\n",
def->cputune.quota);
+
+ if (def->cputune.hypervisor_period)
+ virBufferAsprintf(buf, " <hypervisor_period>%llu"
+ "</hypervisor_period>\n",
+ def->cputune.hypervisor_period);
+
+ if (def->cputune.hypervisor_period)
+ virBufferAsprintf(buf, " <hypervisor_quota>%lld"
+ "</hypervisor_quota>\n",
+ def->cputune.hypervisor_quota);
+
if (def->cputune.vcpupin) {
for (i = 0; i < def->cputune.nvcpupin; i++) {
virBufferAsprintf(buf, " <vcpupin vcpu='%u' ",
@@ -12439,7 +12459,8 @@ virDomainDefFormatInternal(virDomainDefPtr def,
}
if (def->cputune.shares || def->cputune.vcpupin ||
- def->cputune.period || def->cputune.quota)
+ def->cputune.period || def->cputune.quota ||
+ def->cputune.hypervisor_period || def->cputune.hypervisor_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 0eed60e..2a37e26 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1558,6 +1558,8 @@ struct _virDomainDef {
unsigned long shares;
unsigned long long period;
long long quota;
+ unsigned long long hypervisor_period;
+ long long hypervisor_quota;
int nvcpupin;
virDomainVcpuPinDefPtr *vcpupin;
} cputune;
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index 727c0d4..7c6ef33 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -493,17 +493,23 @@ 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;
- }
+ /*
+ * Set cpu bandwidth for the vm if any of the following is true:
+ * 1. we donot know VCPU<->PID mapping or all vcpus run in the same thread
+ * 2. the hypervisor threads are not limited(quota <= 0)
+ */
+ if ((period || quota) &&
+ 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 (priv->nvcpupids == 0 || priv->vcpupids[0] == vm->pid ||
+ vm->def->cputune.hypervisor_quota <= 0) {
if (quota > 0)
vm_quota = quota * vm->def->vcpus;
else
@@ -514,7 +520,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 vcpu runs in the same
+ /* If we donot know VCPU<->PID mapping or all vcpus run in the same
* thread, we cannot control each vcpu.
*/
virCgroupFree(&cgroup);
@@ -570,6 +576,8 @@ int qemuSetupCgroupForHypervisor(struct qemud_driver *driver,
virCgroupPtr cgroup = NULL;
virCgroupPtr cgroup_hypervisor = NULL;
qemuDomainObjPrivatePtr priv = vm->privateData;
+ unsigned long long period = vm->def->cputune.hypervisor_period;
+ long long quota = vm->def->cputune.hypervisor_quota;
int rc;
if (driver->cgroup == NULL)
@@ -608,6 +616,13 @@ int qemuSetupCgroupForHypervisor(struct qemud_driver *driver,
goto cleanup;
}
+ if (period || quota) {
+ if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) {
+ if (qemuSetupCgroupVcpuBW(cgroup_hypervisor, period, quota) < 0)
+ goto cleanup;
+ }
+ }
+
virCgroupFree(&cgroup_hypervisor);
virCgroupFree(&cgroup);
return 0;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index c3555ca..2e40aee 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -7007,6 +7007,7 @@ qemuSetVcpusBWLive(virDomainObjPtr vm, virCgroupPtr cgroup,
int rc;
long long vm_quota = 0;
long long old_quota = 0;
+ long long hypervisor_quota = vm->def->cputune.hypervisor_quota;
unsigned long long old_period = 0;
if (period == 0 && quota == 0)
@@ -7039,6 +7040,16 @@ qemuSetVcpusBWLive(virDomainObjPtr vm, virCgroupPtr cgroup,
goto cleanup;
}
+ /* If we donot know VCPU<->PID mapping or all vcpu runs in the same
+ * thread, we cannot control each vcpu. So we only modify cpu bandwidth
+ * for the vm.
+ */
+ if (priv->nvcpupids == 0 || priv->vcpupids[0] == vm->pid) {
+ if (qemuSetupCgroupVcpuBW(cgroup, period, vm_quota) < 0)
+ goto cleanup;
+ return 0;
+ }
+
/*
* If quota will be changed to a small value, we should modify vcpu's quota
* first. Otherwise, we should modify vm's quota first.
@@ -7048,8 +7059,12 @@ qemuSetVcpusBWLive(virDomainObjPtr vm, virCgroupPtr cgroup,
*
* If both quota and period will be changed to a big/small value, we cannot
* modify period and quota together.
+ *
+ * If the hypervisor threads are limited, we can update period for vm first,
+ * and then we can modify period and quota for the vcpu together even if
+ * they will be changed to a big/small value.
*/
- if ((quota != 0) && (period != 0)) {
+ if (hypervisor_quota <= 0 && quota != 0 && period != 0) {
if (((quota > old_quota) && (period > old_period)) ||
((quota < old_quota) && (period < old_period))) {
/* modify period */
@@ -7063,40 +7078,44 @@ qemuSetVcpusBWLive(virDomainObjPtr vm, virCgroupPtr cgroup,
}
}
- 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;
-
- /* 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 the hypervisor threads are not limited, set cpu bandwidth for the
+ * vm.
*/
- 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)
+ if (vm->def->cputune.hypervisor_quota <= 0) {
+ if (((vm_quota != 0) && (vm_quota > old_quota)) ||
+ ((period != 0) && (period < old_period)))
+ if (qemuSetupCgroupVcpuBW(cgroup, period, vm_quota) < 0)
goto cleanup;
+ }
- virCgroupFree(&cgroup_vcpu);
+ /* each vcpu has a separated thread, so we modify cpu bandwidth for vcpu. */
+ 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 (((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)
+ if (qemuSetupCgroupVcpuBW(cgroup_vcpu, period, quota) < 0)
goto cleanup;
+ virCgroupFree(&cgroup_vcpu);
+ }
+
+ /*
+ * If the hypervisor threads are not limited, set cpu bandwidth for the vm.
+ */
+ if (hypervisor_quota <= 0) {
+ if (((vm_quota != 0) && (vm_quota <= old_quota)) ||
+ ((period != 0) && (period >= old_period)))
+ if (qemuSetupCgroupVcpuBW(cgroup, period, vm_quota) < 0)
+ goto cleanup;
+ }
+
return 0;
cleanup:
--
1.7.1