+Thu May 22 11:24:29 EST 2008 Daniel P. Berrange <berrange@redhat.com>
+
+ Support for NUMA info in the QEMU driver
+ * configure.in: check for libnuma
+ * libvirt.spec.in: add requirement on libnuma-devel at build
+ * src/Makefile.am: add NUMA compiler / linker flags
+ * src/qemu_conf.c: populate capabilities data with NUMA topology
+ * src/qemu_driver.c: implement free memory APIs
+
Thu May 22 11:15:29 EST 2008 Daniel P. Berrange <berrange@redhat.com>
Support the free memory API calls in the remote driver/daemon
AC_SUBST(SELINUX_CFLAGS)
AC_SUBST(SELINUX_LIBS)
+dnl NUMA lib
+AC_ARG_WITH(numactl,
+ [ --with-numactl use numactl for host topology info],
+ [],
+ [with_numactl=check])
+
+NUMACTL_CFLAGS=
+NUMACTL_LIBS=
+if test "$with_qemu" = "yes" -a "$with_numactl" != "no"; then
+ old_cflags="$CFLAGS"
+ old_libs="$LIBS"
+ if test "$with_numactl" = "check"; then
+ AC_CHECK_HEADER([numa.h],[],[with_numactl=no])
+ AC_CHECK_LIB(numa, numa_available,[],[with_numactl=no])
+ if test "$with_numactl" != "no"; then
+ with_numactl="yes"
+ fi
+ else
+ AC_CHECK_HEADER([numa.h],[],
+ [AC_MSG_ERROR([You must install the numactl development package in order to compile libvirt])])
+ AC_CHECK_LIB(numa, numa_available,[],
+ [AC_MSG_ERROR([You must install the numactl development package in order to compile and run libvirt])])
+ fi
+ CFLAGS="$old_cflags"
+ LIBS="$old_libs"
+fi
+if test "$with_numactl" = "yes"; then
+ NUMACTL_LIBS="-lnuma"
+ AC_DEFINE_UNQUOTED(HAVE_NUMACTL, 1, [whether Numactl is available for security])
+fi
+AM_CONDITIONAL(HAVE_NUMACTL, [test "$with_numactl" != "no"])
+AC_SUBST(NUMACTL_CFLAGS)
+AC_SUBST(NUMACTL_LIBS)
+
dnl virsh libraries
AC_CHECK_HEADERS([readline/readline.h])
else
AC_MSG_NOTICE([ selinux: no])
fi
+if test "$with_numactl" = "yes" ; then
+AC_MSG_NOTICE([ numactl: $NUMACTL_CFLAGS $NUMACTL_LIBS])
+else
+AC_MSG_NOTICE([ numactl: no])
+fi
AC_MSG_NOTICE([])
AC_MSG_NOTICE([Miscellaneous])
AC_MSG_NOTICE([])
BuildRequires: bridge-utils
BuildRequires: qemu
BuildRequires: cyrus-sasl-devel
+%if %{with_qemu}
+BuildRequires: numactl-devel
+%endif
%if %{with_polkit}
BuildRequires: PolicyKit-devel >= 0.6
%endif
$(GNUTLS_CFLAGS) \
$(SASL_CFLAGS) \
$(SELINUX_CFLAGS) \
+ $(NUMACTL_CFLAGS) \
-DBINDIR=\""$(libexecdir)"\" \
-DSBINDIR=\""$(sbindir)"\" \
-DSYSCONF_DIR="\"$(sysconfdir)\"" \
libvirt_la_SOURCES = $(CLIENT_SOURCES) $(SERVER_SOURCES)
libvirt_la_LIBADD = $(LIBXML_LIBS) $(GNUTLS_LIBS) $(SASL_LIBS) $(SELINUX_LIBS) \
+ $(NUMACTL_LIBS) \
@CYGWIN_EXTRA_LIBADD@ ../gnulib/lib/libgnu.la
libvirt_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libvirt_sym.version \
-version-info @LIBVIRT_VERSION_INFO@ \
#include <libxml/xpath.h>
#include <libxml/uri.h>
+#if HAVE_NUMACTL
+#include <numa.h>
+#endif
+
#include "libvirt/virterror.h"
#include "qemu_conf.h"
#include "buf.h"
#include "conf.h"
#include "util.h"
+#include "memory.h"
#include "verify.h"
#include "c-ctype.h"
return 0;
}
+#if HAVE_NUMACTL
+#define MAX_CPUS 4096
+#define MAX_CPUS_MASK_SIZE (sizeof(unsigned long))
+#define MAX_CPUS_MASK_LEN (MAX_CPUS / MAX_CPUS_MASK_SIZE)
+#define MAX_CPUS_MASK_BYTES (MAX_CPUS / 8)
+
+#define MASK_CPU_ISSET(mask, cpu) \
+ (((mask)[((cpu) / MAX_CPUS_MASK_SIZE)] >> ((cpu) % MAX_CPUS_MASK_SIZE)) & 1)
+
+static int
+qemudCapsInitNUMA(virCapsPtr caps)
+{
+ int n, i;
+ unsigned long *mask = NULL;
+ int ncpus;
+ int *cpus = NULL;
+ int ret = -1;
+
+ if (numa_available() < 0)
+ return 0;
+
+ if (VIR_ALLOC_N(mask, MAX_CPUS_MASK_LEN) < 0)
+ goto cleanup;
+
+ for (n = 0 ; n <= numa_max_node() ; n++) {
+ if (numa_node_to_cpus(n, mask, MAX_CPUS_MASK_BYTES) < 0)
+ goto cleanup;
+
+ for (ncpus = 0, i = 0 ; i < MAX_CPUS ; i++)
+ if (MASK_CPU_ISSET(mask, i))
+ ncpus++;
+
+ if (VIR_ALLOC_N(cpus, ncpus) < 0)
+ goto cleanup;
+
+ for (ncpus = 0, i = 0 ; i < MAX_CPUS ; i++)
+ if (MASK_CPU_ISSET(mask, i))
+ cpus[ncpus++] = i;
+
+ if (virCapabilitiesAddHostNUMACell(caps,
+ n,
+ ncpus,
+ cpus) < 0)
+ goto cleanup;
+
+ VIR_FREE(cpus);
+ }
+
+ ret = 0;
+
+cleanup:
+ VIR_FREE(cpus);
+ VIR_FREE(mask);
+ return ret;
+}
+#else
+static int qemudCapsInitNUMA(virCapsPtr caps ATTRIBUTE_UNUSED) { return 0; }
+#endif
+
virCapsPtr qemudCapsInit(void) {
struct utsname utsname;
virCapsPtr caps;
0, 0)) == NULL)
goto no_memory;
+ if (qemudCapsInitNUMA(caps) < 0)
+ goto no_memory;
+
for (i = 0 ; i < (sizeof(arch_info_hvm)/sizeof(arch_info_hvm[0])) ; i++)
if (qemudCapsInitGuest(caps,
utsname.machine,
#include <sys/wait.h>
#include <libxml/uri.h>
+#if HAVE_NUMACTL
+#include <numa.h>
+#endif
+
#include "libvirt/virterror.h"
#include "c-ctype.h"
}
+#if HAVE_NUMACTL
+static int
+qemudNodeGetCellsFreeMemory(virConnectPtr conn,
+ unsigned long long *freeMems,
+ int startCell,
+ int maxCells)
+{
+ int n, lastCell, numCells;
+
+ if (numa_available() < 0) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT,
+ "%s", _("NUMA not supported on this host"));
+ return -1;
+ }
+ lastCell = startCell + maxCells - 1;
+ if (lastCell > numa_max_node())
+ lastCell = numa_max_node();
+
+ for (numCells = 0, n = startCell ; n <= lastCell ; n++) {
+ long long mem;
+ if (numa_node_size64(n, &mem) < 0) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("Failed to query NUMA free memory"));
+ return -1;
+ }
+ freeMems[numCells++] = mem;
+ }
+ return numCells;
+}
+
+static unsigned long long
+qemudNodeGetFreeMemory (virConnectPtr conn)
+{
+ unsigned long long freeMem = 0;
+ int n;
+ if (numa_available() < 0) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT,
+ "%s", _("NUMA not supported on this host"));
+ return -1;
+ }
+
+ for (n = 0 ; n <= numa_max_node() ; n++) {
+ long long mem;
+ if (numa_node_size64(n, &mem) < 0) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("Failed to query NUMA free memory"));
+ return -1;
+ }
+ freeMem += mem;
+ }
+
+ return freeMem;
+}
+
+#endif
static int qemudGetProcessInfo(unsigned long long *cpuTime, int pid) {
char proc[PATH_MAX];
NULL, /* domainMigrateFinish */
qemudDomainBlockStats, /* domainBlockStats */
qemudDomainInterfaceStats, /* domainInterfaceStats */
+#if HAVE_NUMACTL
+ qemudNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
+ qemudNodeGetFreeMemory, /* getFreeMemory */
+#else
NULL, /* nodeGetCellsFreeMemory */
NULL, /* getFreeMemory */
+#endif
};
static virNetworkDriver qemuNetworkDriver = {