Currently, libvirt makes use of sched_setaffinity() to set Guest processes's
cpu affinity. But, sometimes, for instance, when QEmu uses vhost-net, the
kernel part of vhost will create a kernel thread for some purpose. In this
case, such kernel thread won't inherit QEmu's cpu affinity.
This patch enables cpuset cgroup in libvirt and setting cpu affinity by
configuring cpuset cgroup.
Signed-off-by: Gui Jianfeng <guijianfeng(a)cn.fujitsu.com>
---
src/libvirt_private.syms | 1 +
src/qemu/qemu_cgroup.c | 22 ++++++++++++++++++++++
src/qemu/qemu_conf.c | 3 ++-
src/util/cgroup.c | 18 ++++++++++++++++++
src/util/cgroup.h | 2 ++
5 files changed, 45 insertions(+), 1 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 626ac6c..e7aebc7 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -83,6 +83,7 @@ virCgroupMounted;
virCgroupPathOfController;
virCgroupRemove;
virCgroupSetBlkioWeight;
+virCgroupCpusetSetcpus;
virCgroupSetCpuShares;
virCgroupSetFreezerState;
virCgroupSetMemory;
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index 1298924..eb92409 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -296,6 +296,28 @@ int qemuSetupCgroup(struct qemud_driver *driver,
}
}
+ if (vm->def->cpumask != NULL) {
+ if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPUSET)) {
+ char *cpumask = NULL;
+ if ((cpumask =
+ virDomainCpuSetFormat(vm->def->cpumask,
vm->def->cpumasklen)) == NULL)
+ goto cleanup;
+
+ rc = virCgroupCpusetSetcpus(cgroup, cpumask);
+ if(rc != 0) {
+ virReportSystemError(-rc,
+ _("Unable to set cpus for domain %s"),
+ vm->def->name);
+ VIR_FREE(cpumask);
+ goto cleanup;
+ }
+ VIR_FREE(cpumask);
+ } else {
+ qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Cpuset is not available on this host"));
+ }
+ }
+
if (vm->def->blkio.weight != 0) {
if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_BLKIO)) {
rc = virCgroupSetBlkioWeight(cgroup, vm->def->blkio.weight);
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 3d8aba4..8b478c4 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -307,7 +307,8 @@ int qemudLoadDriverConfig(struct qemud_driver *driver,
(1 << VIR_CGROUP_CONTROLLER_CPU) |
(1 << VIR_CGROUP_CONTROLLER_DEVICES) |
(1 << VIR_CGROUP_CONTROLLER_MEMORY) |
- (1 << VIR_CGROUP_CONTROLLER_BLKIO);
+ (1 << VIR_CGROUP_CONTROLLER_BLKIO) |
+ (1 << VIR_CGROUP_CONTROLLER_CPUSET);
}
for (i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i++) {
if (driver->cgroupControllers & (1 << i)) {
diff --git a/src/util/cgroup.c b/src/util/cgroup.c
index 2e5ef46..89b2ad4 100644
--- a/src/util/cgroup.c
+++ b/src/util/cgroup.c
@@ -472,6 +472,24 @@ static int virCgroupCpuSetInherit(virCgroupPtr parent, virCgroupPtr
group)
return rc;
}
+int virCgroupCpusetSetcpus(virCgroupPtr group, char *cpustring)
+{
+ int rc = 0;
+ const char *key = "cpuset.cpus";
+
+ VIR_DEBUG("Cpuset: set %s for %s/%s", cpustring, group->path, key);
+
+ rc = virCgroupSetValueStr(group,
+ VIR_CGROUP_CONTROLLER_CPUSET,
+ key,
+ cpustring);
+
+ if (rc != 0)
+ VIR_ERROR("Failed to set %s for %s/%s", cpustring, group->path,
key);
+
+ return rc;
+}
+
static int virCgroupSetMemoryUseHierarchy(virCgroupPtr group)
{
int rc = 0;
diff --git a/src/util/cgroup.h b/src/util/cgroup.h
index 8ae756d..ca6a68a 100644
--- a/src/util/cgroup.h
+++ b/src/util/cgroup.h
@@ -30,6 +30,8 @@ enum {
VIR_ENUM_DECL(virCgroupController);
+int virCgroupCpusetSetcpus(virCgroupPtr group, char *cpustring);
+
int virCgroupForDriver(const char *name,
virCgroupPtr *group,
int privileged,
--
1.7.1