File libvirt-qemu-cgroup-Properly-set-up-vcpu-pinning.patch of Package libvirt

From e939127cc75e04a31460fb59cf34872d197f74c2 Mon Sep 17 00:00:00 2001
Message-Id: <e939127cc75e04a31460fb59cf34872d197f74c2@dist-git>
From: Peter Krempa <pkrempa@redhat.com>
Date: Thu, 2 Apr 2015 10:31:11 +0200
Subject: [PATCH] qemu: cgroup: Properly set up vcpu pinning

https://bugzilla.redhat.com/show_bug.cgi?id=1198096 [6.7]
https://bugzilla.redhat.com/show_bug.cgi?id=1209891 [6.6.z]

When the default cpuset or automatic numa placement is used libvirt
would place the whole parent cgroup in the specified cpuset. This then
disallowed to re-pin the vcpus to a different cpu.

This patch pins only the vcpu threads to the default cpuset and thus
allows to re-pin them later.

The following config would fail to start:
<domain type='kvm'>
  ...
  <vcpu placement='static' cpuset='0-1' current='2'>4</vcpu>
  <cputune>
    <vcpupin vcpu='0' cpuset='2-3'/>
    ...

This is a regression since 298eb3db0a033777bd5091ff21bea72d5e1839cc that
fixed bug https://bugzilla.redhat.com/show_bug.cgi?id=1012846.

This is a reimplementation based on upstream commit
f0fa9080d47b7aedad6f4884b8879d88688752 , but written from scratch
since the code diverged too much.

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
 src/qemu/qemu_cgroup.c  | 76 ++++++++++++++++++++-----------------------------
 src/qemu/qemu_cgroup.h  |  4 ++-
 src/qemu/qemu_process.c |  2 +-
 3 files changed, 35 insertions(+), 47 deletions(-)

diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index 99be07e..0060bc2 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -432,38 +432,6 @@ int qemuSetupCgroup(struct qemud_driver *driver,
         }
     }
 
-    if (vm->def->cpumask ||
-        (vm->def->placement_mode == VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO)) {
-        char *cpu_mask = NULL;
-
-
-        if (vm->def->placement_mode == VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO) {
-            virBitmapPtr cpumap;
-
-            cpumap = virCapabilitiesGetCpusForNodemask(driver->caps, nodemask);
-            if (!cpumap)
-                goto cleanup;
-            cpu_mask = virBitmapFormat(cpumap);
-            virBitmapFree(cpumap);
-        } else {
-            cpu_mask = virBitmapFormat(vm->def->cpumask);
-        }
-
-        if (!cpu_mask) {
-            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                           _("failed to convert cpu mask"));
-            goto cleanup;
-        }
-
-        rc = virCgroupSetCpusetCpus(cgroup, cpu_mask);
-        VIR_FREE(cpu_mask);
-        if (rc != 0) {
-            virReportSystemError(-rc,
-                                 _("Unable to set cpuset.cpus for domain %s"),
-                                 vm->def->name);
-            goto cleanup;
-        }
-    }
 done:
     virCgroupFree(&cgroup);
 
@@ -568,7 +536,9 @@ cleanup:
     return rc;
 }
 
-int qemuSetupCgroupForVcpu(struct qemud_driver *driver, virDomainObjPtr vm)
+int qemuSetupCgroupForVcpu(struct qemud_driver *driver,
+                           virDomainObjPtr vm,
+                           virBitmapPtr nodemask)
 {
     virCgroupPtr cgroup = NULL;
     virCgroupPtr cgroup_vcpu = NULL;
@@ -578,6 +548,7 @@ int qemuSetupCgroupForVcpu(struct qemud_driver *driver, virDomainObjPtr vm)
     unsigned int i, j;
     unsigned long long period = vm->def->cputune.period;
     long long quota = vm->def->cputune.quota;
+    virBitmapPtr autoCpuset = NULL;
 
     if ((period || quota) &&
         (!driver->cgroup ||
@@ -611,6 +582,10 @@ int qemuSetupCgroupForVcpu(struct qemud_driver *driver, virDomainObjPtr vm)
         return 0;
     }
 
+    if (vm->def->placement_mode == VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO &&
+        !(autoCpuset = virCapabilitiesGetCpusForNodemask(driver->caps, nodemask)))
+        goto cleanup;
+
     for (i = 0; i < priv->nvcpupids; i++) {
         rc = virCgroupForVcpu(cgroup, i, &cgroup_vcpu, 1);
         if (rc < 0) {
@@ -637,25 +612,34 @@ int qemuSetupCgroupForVcpu(struct qemud_driver *driver, virDomainObjPtr vm)
 
         /* Set vcpupin in cgroup if vcpupin xml is provided */
         if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPUSET)) {
-            /* find the right CPU to pin, otherwise
-             * qemuSetupCgroupVcpuPin will fail. */
+            virBitmapPtr cpumap = NULL;
+
+            /* try to use the default cpu maps */
+            if (vm->def->placement_mode == VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO)
+                cpumap = autoCpuset;
+            else
+                cpumap = vm->def->cpumask;
+
+
+            /* lookup a more specific pinning info */
             for (j = 0; j < def->cputune.nvcpupin; j++) {
-                if (def->cputune.vcpupin[j]->vcpuid != i)
-                    continue;
-
-                if (qemuSetupCgroupVcpuPin(cgroup_vcpu,
-                                           def->cputune.vcpupin,
-                                           def->cputune.nvcpupin,
-                                           i) < 0)
-                    goto cleanup;
-
-                break;
+                if (def->cputune.vcpupin[j]->vcpuid == i) {
+                    cpumap = def->cputune.vcpupin[j]->cpumask;
+                    break;
+                }
             }
+
+            if (!cpumap)
+                continue;
+
+            if (qemuSetupCgroupEmulatorPin(cgroup_vcpu, cpumap) < 0)
+                goto cleanup;
         }
 
         virCgroupFree(&cgroup_vcpu);
     }
 
+    virBitmapFree(autoCpuset);
     virCgroupFree(&cgroup);
     return 0;
 
@@ -670,6 +654,8 @@ cleanup:
         virCgroupFree(&cgroup);
     }
 
+    virBitmapFree(autoCpuset);
+
     return -1;
 }
 
diff --git a/src/qemu/qemu_cgroup.h b/src/qemu/qemu_cgroup.h
index 50ee092..ed5d757 100644
--- a/src/qemu/qemu_cgroup.h
+++ b/src/qemu/qemu_cgroup.h
@@ -56,7 +56,9 @@ int qemuSetupCgroupVcpuPin(virCgroupPtr cgroup,
                            int nvcpupin,
                            int vcpuid);
 int qemuSetupCgroupEmulatorPin(virCgroupPtr cgroup, virBitmapPtr cpumask);
-int qemuSetupCgroupForVcpu(struct qemud_driver *driver, virDomainObjPtr vm);
+int qemuSetupCgroupForVcpu(struct qemud_driver *driver,
+                           virDomainObjPtr vm,
+                           virBitmapPtr nodemask);
 int qemuSetupCgroupForEmulator(struct qemud_driver *driver,
                                virDomainObjPtr vm,
                                virBitmapPtr nodemask);
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index e872497..3e00afb 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -4199,7 +4199,7 @@ int qemuProcessStart(virConnectPtr conn,
         goto cleanup;
 
     VIR_DEBUG("Setting cgroup for each VCPU (if required)");
-    if (qemuSetupCgroupForVcpu(driver, vm) < 0)
+    if (qemuSetupCgroupForVcpu(driver, vm, nodemask) < 0)
         goto cleanup;
 
     VIR_DEBUG("Setting cgroup for emulator (if required)");
-- 
2.3.5

openSUSE Build Service is sponsored by