[libvirt] [PATCH RFC 4/5] qemu: Implement cfs_period and cfs_quota's modification

Wen Congyang wency at cn.fujitsu.com
Wed Jun 15 06:32:17 UTC 2011


---
 src/qemu/qemu_driver.c |  162 +++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 139 insertions(+), 23 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 853c84c..0d83c04 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4764,6 +4764,7 @@ static char *qemuGetSchedulerType(virDomainPtr dom,
 {
     struct qemud_driver *driver = dom->conn->privateData;
     char *ret = NULL;
+    char *cfs_period_path = NULL;
 
     qemuDriverLock(driver);
     if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) {
@@ -4772,14 +4773,29 @@ static char *qemuGetSchedulerType(virDomainPtr dom,
         goto cleanup;
     }
 
-    if (nparams)
-        *nparams = 1;
+    /* check whether the host supports CFS bandwidth */
+    if (virCgroupPathOfController(driver->cgroup, VIR_CGROUP_CONTROLLER_CPU,
+                              "cpu.cfs_period_us", &cfs_period_path) < 0) {
+        qemuReportError(VIR_ERR_INTERNAL_ERROR,
+                        "%s",
+                        _("cannot get the path of cgroup CPU controller"));
+        goto cleanup;
+    }
+
+    if (nparams) {
+        if (access(cfs_period_path, F_OK) < 0) {
+            *nparams = 1;
+        } else {
+            *nparams = 3;
+        }
+    }
 
     ret = strdup("posix");
     if (!ret)
         virReportOOMError();
 
 cleanup:
+    VIR_FREE(cfs_period_path);
     qemuDriverUnlock(driver);
     return ret;
 }
@@ -5313,9 +5329,10 @@ static int qemuSetSchedulerParametersFlags(virDomainPtr dom,
     int i;
     virCgroupPtr group = NULL;
     virDomainObjPtr vm = NULL;
-    virDomainDefPtr persistentDef = NULL;
+    virDomainDefPtr vmdef = NULL;
     int ret = -1;
     bool isActive;
+    int rc;
 
     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                   VIR_DOMAIN_AFFECT_CONFIG, -1);
@@ -5339,10 +5356,17 @@ static int qemuSetSchedulerParametersFlags(virDomainPtr dom,
             flags = VIR_DOMAIN_AFFECT_CONFIG;
     }
 
-    if ((flags & VIR_DOMAIN_AFFECT_CONFIG) && !vm->persistent) {
-        qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
-                        _("cannot change persistent config of a transient domain"));
-        goto cleanup;
+    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
+        if (vm->persistent) {
+            qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                            _("cannot change persistent config of a transient domain"));
+            goto cleanup;
+        }
+
+        /* Make a copy for updated domain. */
+        vmdef = virDomainObjCopyPersistentDef(driver->caps, vm);
+        if (!vmdef)
+            goto cleanup;
     }
 
     if (flags & VIR_DOMAIN_AFFECT_LIVE) {
@@ -5369,7 +5393,6 @@ static int qemuSetSchedulerParametersFlags(virDomainPtr dom,
         virTypedParameterPtr param = &params[i];
 
         if (STREQ(param->field, "cpu_shares")) {
-            int rc;
             if (param->type != VIR_TYPED_PARAM_ULLONG) {
                 qemuReportError(VIR_ERR_INVALID_ARG, "%s",
                                 _("invalid type for cpu_shares tunable, expected a 'ullong'"));
@@ -5388,19 +5411,53 @@ static int qemuSetSchedulerParametersFlags(virDomainPtr dom,
             }
 
             if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
-                persistentDef = virDomainObjGetPersistentDef(driver->caps, vm);
-                if (!persistentDef) {
-                    qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                                    _("can't get persistentDef"));
+                vmdef->cputune.shares = params[i].value.ul;
+            }
+        } else if (STREQ(param->field, "cfs_period")) {
+            if (param->type != VIR_TYPED_PARAM_ULLONG) {
+                qemuReportError(VIR_ERR_INVALID_ARG, "%s",
+                                _("invalid type for cfs_period tunable,"
+                                  " expected a 'ullong'"));
+                goto cleanup;
+            }
+
+            if (flags & VIR_DOMAIN_AFFECT_LIVE) {
+                rc = virCgroupSetCpuCfsPeriod(group, params[i].value.ul);
+                if (rc != 0) {
+                    virReportSystemError(-rc, "%s",
+                                         _("unable to set cpu bandwidth period"
+                                           " tunable"));
                     goto cleanup;
                 }
-                persistentDef->cputune.shares = params[i].value.ul;
-                rc = virDomainSaveConfig(driver->configDir, persistentDef);
-                if (rc) {
-                    qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                                    _("can't save config"));
+
+                vm->def->cputune.period = params[i].value.ul;
+            }
+
+            if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
+                vmdef->cputune.period = params[i].value.ul;
+            }
+        } else if (STREQ(param->field, "cfs_quota")) {
+            if (param->type != VIR_TYPED_PARAM_LLONG) {
+                qemuReportError(VIR_ERR_INVALID_ARG, "%s",
+                                _("invalid type for cfs_quota tunable,"
+                                  " expected a 'llong'"));
+                goto cleanup;
+            }
+
+            if (flags & VIR_DOMAIN_AFFECT_LIVE) {
+                rc = virCgroupSetCpuCfsQuota(group, params[i].value.l);
+                if (rc != 0) {
+                    virReportSystemError(-rc, "%s",
+                                         _("unable to set cpu bandwidth"
+                                           " tunable"));
                     goto cleanup;
                 }
+
+                vm->def->cputune.quota = params[i].value.l;
+            }
+
+            if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
+                vmdef->cputune.quota = params[i].value.l;
             }
         } else {
             qemuReportError(VIR_ERR_INVALID_ARG,
@@ -5409,6 +5466,15 @@ static int qemuSetSchedulerParametersFlags(virDomainPtr dom,
         }
     }
 
+    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
+        rc = virDomainSaveConfig(driver->configDir, vmdef);
+        if (rc) {
+            qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                            _("can't save config"));
+            goto cleanup;
+        }
+    }
+
     ret = 0;
 
 cleanup:
@@ -5438,7 +5504,9 @@ qemuGetSchedulerParametersFlags(virDomainPtr dom,
     struct qemud_driver *driver = dom->conn->privateData;
     virCgroupPtr group = NULL;
     virDomainObjPtr vm = NULL;
-    unsigned long long val;
+    unsigned long long shares;
+    unsigned long long period;
+    long long quota;
     int ret = -1;
     int rc;
     bool isActive;
@@ -5493,9 +5561,17 @@ qemuGetSchedulerParametersFlags(virDomainPtr dom,
                                 _("can't get persistentDef"));
                 goto cleanup;
             }
-            val = persistentDef->cputune.shares;
+            shares = persistentDef->cputune.shares;
+            if (*nparams > 1) {
+                period = persistentDef->cputune.period;
+                quota = persistentDef->cputune.quota;
+            }
         } else {
-            val = vm->def->cputune.shares;
+            shares = vm->def->cputune.shares;
+            if (*nparams > 1) {
+                period = vm->def->cputune.period;
+                quota = vm->def->cputune.quota;
+            }
         }
         goto out;
     }
@@ -5518,14 +5594,31 @@ qemuGetSchedulerParametersFlags(virDomainPtr dom,
         goto cleanup;
     }
 
-    rc = virCgroupGetCpuShares(group, &val);
+    rc = virCgroupGetCpuShares(group, &shares);
     if (rc != 0) {
         virReportSystemError(-rc, "%s",
                              _("unable to get cpu shares tunable"));
         goto cleanup;
     }
+
+    if (*nparams > 1) {
+        rc = virCgroupGetCpuCfsPeriod(group, &period);
+        if (rc != 0) {
+            virReportSystemError(-rc, "%s",
+                                 _("unable to get cpu bandwidth period"
+                                   " tunable"));
+            goto cleanup;
+        }
+
+        rc = virCgroupGetCpuCfsQuota(group, &quota);
+        if (rc != 0) {
+            virReportSystemError(-rc, "%s",
+                                 _("unable to get cpu bandwidth tunable"));
+            goto cleanup;
+        }
+    }
 out:
-    params[0].value.ul = val;
+    params[0].value.ul = shares;
     params[0].type = VIR_TYPED_PARAM_ULLONG;
     if (virStrcpyStatic(params[0].field, "cpu_shares") == NULL) {
         qemuReportError(VIR_ERR_INTERNAL_ERROR,
@@ -5533,7 +5626,30 @@ out:
         goto cleanup;
     }
 
-    *nparams = 1;
+    if (*nparams > 1) {
+        params[1].value.ul = period;
+        params[1].type = VIR_TYPED_PARAM_ULLONG;
+        if (virStrcpyStatic(params[1].field, "cfs_period") == NULL) {
+            qemuReportError(VIR_ERR_INTERNAL_ERROR,
+                            "%s",
+                            _("Field cfs_period too long for destination"));
+            goto cleanup;
+        }
+
+        params[2].value.ul = quota;
+        params[2].type = VIR_TYPED_PARAM_LLONG;
+        if (virStrcpyStatic(params[2].field, "cfs_quota") == NULL) {
+            qemuReportError(VIR_ERR_INTERNAL_ERROR,
+                            "%s",
+                            _("Field cfs_quota too long for destination"));
+            goto cleanup;
+        }
+
+        *nparams = 3;
+    } else {
+        *nparams = 1;
+    }
+
     ret = 0;
 
 cleanup:
-- 
1.7.1




More information about the libvir-list mailing list