[libvirt] [PATCH 2/3] lxc: Implement emulator pin API in lxc driver

Wang Rui moon.wangrui at huawei.com
Thu Sep 4 07:52:34 UTC 2014


From: Yue Wenyuan <yuewenyuan at huawei.com>

Implement the lxc driver method for virDomainPinEmulator
to set container's cpuset.

Signed-off-by: Wang Rui <moon.wangrui at huawei.com>
Signed-off-by: Yue Wenyuan <yuewenyuan at huawei.com>
---
 src/lxc/lxc_cgroup.c |  20 ++++++++
 src/lxc/lxc_cgroup.h |   3 ++
 src/lxc/lxc_driver.c | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 154 insertions(+)

diff --git a/src/lxc/lxc_cgroup.c b/src/lxc/lxc_cgroup.c
index f696bf8..7dc7c9b 100644
--- a/src/lxc/lxc_cgroup.c
+++ b/src/lxc/lxc_cgroup.c
@@ -531,6 +531,26 @@ int virLXCCgroupSetup(virDomainDefPtr def,
     return ret;
 }
 
+int
+virLXCSetupCgroupEmulatorPin(virCgroupPtr cgroup,
+                           virBitmapPtr cpumask)
+{
+    int ret = -1;
+    char *new_cpus = NULL;
+
+    if (!(new_cpus = virBitmapFormat(cpumask)))
+        goto cleanup;
+
+    if (virCgroupSetCpusetCpus(cgroup, new_cpus) < 0)
+        goto cleanup;
+
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(new_cpus);
+    return ret;
+}
+
 static int virLXCCgroupSetupCpusetTuneForEmulator(virDomainDefPtr def,
                                        virCgroupPtr cgroup,
                                        virBitmapPtr nodemask)
diff --git a/src/lxc/lxc_cgroup.h b/src/lxc/lxc_cgroup.h
index 32086c5..8011a32 100644
--- a/src/lxc/lxc_cgroup.h
+++ b/src/lxc/lxc_cgroup.h
@@ -33,6 +33,9 @@ int virLXCCgroupSetup(virDomainDefPtr def,
                       virCgroupPtr cgroup,
                       virBitmapPtr nodemask);
 
+int virLXCSetupCgroupEmulatorPin(virCgroupPtr cgroup,
+                           virBitmapPtr cpumask);
+
 int virLXCCgroupSetupForEmulator(virDomainDefPtr def,
                       virCgroupPtr cgroup,
                       virBitmapPtr nodemask);
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index 66d708a..9e3a877 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -1264,6 +1264,136 @@ lxcDomainCreateXML(virConnectPtr conn,
     return lxcDomainCreateXMLWithFiles(conn, xml, 0, NULL,  flags);
 }
 
+static int
+lxcDomainPinEmulator(virDomainPtr dom,
+                      unsigned char *cpumap,
+                      int maplen,
+                      unsigned int flags)
+{
+    virLXCDriverPtr driver =  dom->conn->privateData;
+    virDomainObjPtr vm;
+    virCgroupPtr cgroup_emulator = NULL;
+    pid_t pid;
+    virDomainDefPtr persistentDef = NULL;
+    int ret = -1;
+    virLXCDomainObjPrivatePtr priv;
+    bool doReset = false;
+    virBitmapPtr pcpumap = NULL;
+    virLXCDriverConfigPtr cfg = NULL;
+    virCapsPtr caps = NULL;
+
+    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+                  VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+    cfg = virLXCDriverGetConfig(driver);
+
+    if (!(vm = lxcDomObjFromDomain(dom)))
+        goto cleanup;
+
+    if (virDomainPinEmulatorEnsureACL(dom->conn, vm->def, flags) < 0)
+        goto cleanup;
+
+    if (!(caps = virLXCDriverGetCapabilities(driver, false)))
+        goto cleanup;
+
+    if (vm->def->placement_mode == VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("Changing affinity for emulator thread dynamically "
+                         "is not allowed when CPU placement is 'auto'"));
+        goto cleanup;
+    }
+
+    if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
+                                        &persistentDef) < 0)
+        goto cleanup;
+
+    priv = vm->privateData;
+
+    pcpumap = virBitmapNewData(cpumap, maplen);
+    if (!pcpumap)
+        goto cleanup;
+
+    if (virBitmapIsAllClear(pcpumap)) {
+        virReportError(VIR_ERR_INVALID_ARG, "%s",
+                       _("Empty cpu list for pinning"));
+        goto cleanup;
+    }
+
+    if (virBitmapIsAllSet(pcpumap))
+        doReset = true;
+
+    pid = vm->pid;
+
+    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
+        if (virCgroupHasController(priv->cgroup,
+                                       VIR_CGROUP_CONTROLLER_CPUSET)) {
+            if (virCgroupNewEmulator(priv->cgroup, false, &cgroup_emulator) < 0)
+                goto cleanup;
+            if (virLXCSetupCgroupEmulatorPin(cgroup_emulator,
+                                           pcpumap) < 0) {
+                virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                               _("failed to set cpuset.cpus in cgroup "
+                                 "for lxc emulator"));
+                goto cleanup;
+            }
+        } else {
+            virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
+                           _("there is not cgroup controller for "
+                             "lxc emulator"));
+            goto cleanup;
+        }
+        if (doReset) {
+           if (virDomainEmulatorPinDel(vm->def) < 0) {
+               virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                              _("failed to delete emulatorpin xml of "
+                                "a running domain"));
+                goto cleanup;
+            }
+        } else {
+            if (virDomainEmulatorPinAdd(vm->def, cpumap, maplen) < 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("failed to update or add emulatorpin xml "
+                                 "of a running domain"));
+                goto cleanup;
+            }
+        }
+        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
+            goto cleanup;
+    }
+
+    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
+        if (doReset) {
+            if (virDomainEmulatorPinDel(persistentDef) < 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("failed to delete emulatorpin xml of "
+                                 "a persistent domain"));
+                goto cleanup;
+            }
+        } else {
+            if (virDomainEmulatorPinAdd(persistentDef, cpumap, maplen) < 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("failed to update or add emulatorpin xml "
+                                 "of a persistent domain"));
+                goto cleanup;
+            }
+        }
+
+        ret = virDomainSaveConfig(cfg->configDir, persistentDef);
+        goto cleanup;
+    }
+
+    ret = 0;
+
+ cleanup:
+    if (cgroup_emulator)
+        virCgroupFree(&cgroup_emulator);
+    virBitmapFree(pcpumap);
+    virObjectUnref(caps);
+    if (vm)
+        virObjectUnlock(vm);
+    virObjectUnref(cfg);
+    return ret;
+}
 
 static int lxcDomainGetSecurityLabel(virDomainPtr dom, virSecurityLabelPtr seclabel)
 {
@@ -5700,6 +5830,7 @@ static virDriver lxcDriver = {
     .connectListAllDomains = lxcConnectListAllDomains, /* 0.9.13 */
     .domainCreateXML = lxcDomainCreateXML, /* 0.4.4 */
     .domainCreateXMLWithFiles = lxcDomainCreateXMLWithFiles, /* 1.1.1 */
+    .domainPinEmulator = lxcDomainPinEmulator, /*1.2.9*/
     .domainLookupByID = lxcDomainLookupByID, /* 0.4.2 */
     .domainLookupByUUID = lxcDomainLookupByUUID, /* 0.4.2 */
     .domainLookupByName = lxcDomainLookupByName, /* 0.4.2 */
-- 
1.7.12.4





More information about the libvir-list mailing list