* src/Makefile.am: Add processinfo.h/processinfo.c
* src/util/processinfo.c, src/util/processinfo.h: Module providing
APIs for getting/setting process CPU affinity
* src/qemu/qemu_driver.c: Switch over to new APIs for schedular
affinity
* src/libvirt_private.syms: Export virProcessInfoSetAffinity
and virProcessInfoGetAffinity to internal drivers
---
src/Makefile.am | 4 +-
src/libvirt_private.syms | 5 ++
src/qemu/qemu_driver.c | 73 +++++++++++++--------------------
src/util/processinfo.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++
src/util/processinfo.h | 37 +++++++++++++++++
5 files changed, 175 insertions(+), 45 deletions(-)
create mode 100644 src/util/processinfo.c
create mode 100644 src/util/processinfo.h
diff --git a/src/Makefile.am b/src/Makefile.am
index d22a103..9a3c9c8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -55,6 +55,7 @@ UTIL_SOURCES = \
util/logging.c util/logging.h \
util/memory.c util/memory.h \
util/pci.c util/pci.h \
+ util/processinfo.c util/processinfo.h \
util/hostusb.c util/hostusb.h \
util/network.c util/network.h \
util/qparams.c util/qparams.h \
@@ -268,7 +269,8 @@ NODE_DEVICE_DRIVER_HAL_SOURCES = \
node_device/node_device_hal.h
NODE_DEVICE_DRIVER_UDEV_SOURCES = \
- node_device/node_device_udev.c
+ node_device/node_device_udev.c \
+ node_device/node_device_udev.h
#########################
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index c473d49..e880c2e 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -374,6 +374,11 @@ pciDeviceListUnlock;
pciDeviceListSteal;
+# processinfo.h
+virProcessInfoSetAffinity;
+virProcessInfoGetAffinity;
+
+
# qparams.h
qparam_get_query;
qparam_query_parse;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 968118e..b50cf6f 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -47,10 +47,6 @@
#include <sys/ioctl.h>
#include <sys/un.h>
-#if HAVE_SCHED_H
-#include <sched.h>
-#endif
-
#include "virterror_internal.h"
#include "logging.h"
#include "datatypes.h"
@@ -72,6 +68,7 @@
#include "node_device_conf.h"
#include "pci.h"
#include "hostusb.h"
+#include "processinfo.h"
#include "security/security_driver.h"
#include "cgroup.h"
#include "libvirt_internal.h"
@@ -1359,11 +1356,11 @@ static int
qemudInitCpus(virConnectPtr conn,
virDomainObjPtr vm,
const char *migrateFrom) {
-#if HAVE_SCHED_GETAFFINITY
- cpu_set_t mask;
int i, hostcpus, maxcpu = QEMUD_CPUMASK_LEN;
virNodeInfo nodeinfo;
qemuDomainObjPrivatePtr priv = vm->privateData;
+ unsigned char *cpumap;
+ int cpumaplen;
if (nodeGetInfo(conn, &nodeinfo) < 0)
return -1;
@@ -1374,25 +1371,37 @@ qemudInitCpus(virConnectPtr conn,
if (maxcpu > hostcpus)
maxcpu = hostcpus;
- CPU_ZERO(&mask);
+ cpumaplen = VIR_CPU_MAPLEN(maxcpu);
+ if (VIR_ALLOC_N(cpumap, cpumaplen) < 0) {
+ virReportOOMError(conn);
+ return -1;
+ }
+
if (vm->def->cpumask) {
- for (i = 0 ; i < maxcpu ; i++)
+ /* XXX why don't we keep 'cpumask' in the libvirt cpumap
+ * format to start with ?!?! */
+ for (i = 0 ; i < maxcpu && i < vm->def->cpumasklen ; i++)
if (vm->def->cpumask[i])
- CPU_SET(i, &mask);
+ VIR_USE_CPU(cpumap, i);
} else {
+ /* You may think this is redundant, but we can't assume libvirtd
+ * itself is running on all pCPUs, so we need to explicitly set
+ * the spawned QEMU instance to all pCPUs if no map is given in
+ * its config file */
for (i = 0 ; i < maxcpu ; i++)
- CPU_SET(i, &mask);
+ VIR_USE_CPU(cpumap, i);
}
+ /* The XML config only gives a per-VM affinity, so we apply
+ * the same mapping to all vCPUs */
for (i = 0 ; i < vm->nvcpupids ; i++) {
- if (sched_setaffinity(vm->vcpupids[i],
- sizeof(mask), &mask) < 0) {
- virReportSystemError(conn, errno, "%s",
- _("failed to set CPU affinity"));
+ if (virProcessInfoSetAffinity(vm->vcpupids[i],
+ cpumap, cpumaplen, maxcpu) < 0) {
+ VIR_FREE(cpumap);
return -1;
}
}
-#endif /* HAVE_SCHED_GETAFFINITY */
+ VIR_FREE(cpumap);
/* XXX This resume doesn't really belong here. Move it up to caller */
if (migrateFrom == NULL) {
@@ -3657,7 +3666,6 @@ cleanup:
}
-#if HAVE_SCHED_GETAFFINITY
static int
qemudDomainPinVcpu(virDomainPtr dom,
unsigned int vcpu,
@@ -3665,8 +3673,7 @@ qemudDomainPinVcpu(virDomainPtr dom,
int maplen) {
struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm;
- cpu_set_t mask;
- int i, maxcpu, hostcpus;
+ int maxcpu, hostcpus;
virNodeInfo nodeinfo;
int ret = -1;
@@ -3703,18 +3710,10 @@ qemudDomainPinVcpu(virDomainPtr dom,
if (maxcpu > hostcpus)
maxcpu = hostcpus;
- CPU_ZERO(&mask);
- for (i = 0 ; i < maxcpu ; i++) {
- if (VIR_CPU_USABLE(cpumap, maplen, 0, i))
- CPU_SET(i, &mask);
- }
-
if (vm->vcpupids != NULL) {
- if (sched_setaffinity(vm->vcpupids[vcpu], sizeof(mask), &mask) < 0) {
- virReportSystemError(dom->conn, errno, "%s",
- _("cannot set affinity"));
+ if (virProcessInfoSetAffinity(vm->vcpupids[vcpu],
+ cpumap, maplen, maxcpu) < 0)
goto cleanup;
- }
} else {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
"%s", _("cpu affinity is not supported"));
@@ -3794,19 +3793,11 @@ qemudDomainGetVcpus(virDomainPtr dom,
memset(cpumaps, 0, maplen * maxinfo);
if (vm->vcpupids != NULL) {
for (v = 0 ; v < maxinfo ; v++) {
- cpu_set_t mask;
unsigned char *cpumap = VIR_GET_CPUMAP(cpumaps, maplen, v);
- CPU_ZERO(&mask);
- if (sched_getaffinity(vm->vcpupids[v], sizeof(mask), &mask)
< 0) {
- virReportSystemError(dom->conn, errno, "%s",
- _("cannot get affinity"));
+ if (virProcessInfoGetAffinity(vm->vcpupids[v],
+ cpumap, maplen, maxcpu) < 0)
goto cleanup;
- }
-
- for (i = 0 ; i < maxcpu ; i++)
- if (CPU_ISSET(i, &mask))
- VIR_USE_CPU(cpumap, i);
}
} else {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
@@ -3822,7 +3813,6 @@ cleanup:
virDomainObjUnlock(vm);
return ret;
}
-#endif /* HAVE_SCHED_GETAFFINITY */
static int qemudDomainGetMaxVcpus(virDomainPtr dom) {
@@ -7510,13 +7500,8 @@ static virDriver qemuDriver = {
qemudDomainRestore, /* domainRestore */
qemudDomainCoreDump, /* domainCoreDump */
qemudDomainSetVcpus, /* domainSetVcpus */
-#if HAVE_SCHED_GETAFFINITY
qemudDomainPinVcpu, /* domainPinVcpu */
qemudDomainGetVcpus, /* domainGetVcpus */
-#else
- NULL, /* domainPinVcpu */
- NULL, /* domainGetVcpus */
-#endif
qemudDomainGetMaxVcpus, /* domainGetMaxVcpus */
qemudDomainGetSecurityLabel, /* domainGetSecurityLabel */
qemudNodeGetSecurityModel, /* nodeGetSecurityModel */
diff --git a/src/util/processinfo.c b/src/util/processinfo.c
new file mode 100644
index 0000000..aaffd88
--- /dev/null
+++ b/src/util/processinfo.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors:
+ * Daniel P. Berrange <berrange(a)redhat.com>
+ */
+
+#include <config.h>
+
+#if HAVE_SCHED_H
+#include <sched.h>
+#endif
+
+#include "processinfo.h"
+#include "virterror_internal.h"
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+#if HAVE_SCHED_GETAFFINITY
+
+int virProcessInfoSetAffinity(pid_t pid,
+ const unsigned char *map,
+ size_t maplen,
+ int maxcpu)
+{
+ int i;
+ cpu_set_t mask;
+
+ CPU_ZERO(&mask);
+ for (i = 0 ; i < maxcpu ; i++) {
+ if (VIR_CPU_USABLE(map, maplen, 0, i))
+ CPU_SET(i, &mask);
+ }
+
+ if (sched_setaffinity(pid, sizeof(mask), &mask) < 0) {
+ virReportSystemError(NULL, errno,
+ _("cannot set CPU affinity on process %d"), pid);
+ return -1;
+ }
+
+ return 0;
+}
+
+int virProcessInfoGetAffinity(pid_t pid,
+ unsigned char *map,
+ size_t maplen ATTRIBUTE_UNUSED,
+ int maxcpu)
+{
+ int i;
+ cpu_set_t mask;
+
+ CPU_ZERO(&mask);
+ if (sched_getaffinity(pid, sizeof(mask), &mask) < 0) {
+ virReportSystemError(NULL, errno,
+ _("cannot set CPU affinity on process %d"), pid);
+ return -1;
+ }
+
+ for (i = 0 ; i < maxcpu ; i++)
+ if (CPU_ISSET(i, &mask))
+ VIR_USE_CPU(map, i);
+
+ return 0;
+}
+
+#else /* HAVE_SCHED_GETAFFINITY */
+
+int virProcessInfoSetAffinity(pid_t pid ATTRIBUTE_UNUSED,
+ unsigned char *map ATTRIBUTE_UNUSED,
+ size_t maplen ATTRIBUTE_UNUSED,
+ int maxcpu ATTRIBUTE_UNUSED)
+{
+ virReportSystemError(NULL, ENOSYS, "%s",
+ _("Process CPU affinity is not supported on this
platform"));
+ return -1;
+}
+
+int virProcessInfoGetAffinity(pid_t pid ATTRIBUTE_UNUSED,
+ unsigned char *map ATTRIBUTE_UNUSED,
+ size_t maplen ATTRIBUTE_UNUSED,
+ int maxcpu ATTRIBUTE_UNUSED)
+{
+ virReportSystemError(NULL, ENOSYS, "%s",
+ _("Process CPU affinity is not supported on this
platform"));
+ return -1;
+}
+#endif /* HAVE_SCHED_GETAFFINITY */
diff --git a/src/util/processinfo.h b/src/util/processinfo.h
new file mode 100644
index 0000000..17800bd
--- /dev/null
+++ b/src/util/processinfo.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors:
+ * Daniel P. Berrange <berrange(a)redhat.com>
+ */
+
+#ifndef __VIR_PROCESSINFO_H__
+#define __VIR_PROCESSINFO_H__
+
+#include "internal.h"
+
+int virProcessInfoSetAffinity(pid_t pid,
+ const unsigned char *map,
+ size_t maplen,
+ int maxcpu);
+
+int virProcessInfoGetAffinity(pid_t pid,
+ unsigned char *map,
+ size_t maplen,
+ int maxcpu);
+
+#endif /* __VIR_PROCESSINFO_H__ */
--
1.6.5.2