This patch first sets cpuset.cpus to lastest value for libvirtd,
and then registers 2 callback for cpu hotplug event for libvirtd:
- daemonNetlinkCpuHotplugHandleCallback()
- daemonNetlinkCpuHotplugRemoveCallback()
Signed-off-by: Tang Chen <tangchen(a)cn.fujitsu.com>
---
daemon/libvirtd.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++
src/libvirt_private.syms | 1 +
src/util/cgroup.c | 6 ++---
src/util/cgroup.h | 4 +++
4 files changed, 70 insertions(+), 3 deletions(-)
diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
index 6973df6..b612231 100644
--- a/daemon/libvirtd.c
+++ b/daemon/libvirtd.c
@@ -56,6 +56,8 @@
#include "uuid.h"
#include "viraudit.h"
#include "locking/lock_manager.h"
+#include "cgroup.h"
+#include "hotplug.h"
#ifdef WITH_DRIVER_MODULES
# include "driver.h"
@@ -935,6 +937,43 @@ enum {
OPT_VERSION = 129
};
+static void
+daemonNetlinkCpuHotplugHandleCallback(unsigned char *msg,
+ int length,
+ struct sockaddr_nl *peer ATTRIBUTE_UNUSED,
+ bool *handled ATTRIBUTE_UNUSED,
+ void *opaque)
+{
+ virCgroupPtr cgroup = NULL;
+
+ /* opaque is a cgroup identifier pointing to libvirt root cgroup. */
+ if (!opaque) {
+ virReportSystemError(EINVAL,
+ "%s",
+ _("invalid argument"));
+ return;
+ }
+
+ cgroup = (virCgroupPtr)opaque;
+
+ if (virHotplugUpdateCgroupCpuset(msg, length, cgroup) < 0) {
+ virReportSystemError(errno,
+ "%s",
+ _("Unable to update cpuset in cgroup"));
+ }
+
+ return;
+}
+
+static void
+daemonNetlinkCpuHotplugRemoveCallback(int watch ATTRIBUTE_UNUSED,
+ const virMacAddrPtr macaddr ATTRIBUTE_UNUSED,
+ void *opaque ATTRIBUTE_UNUSED)
+{
+ /* For now, nothing to do. */
+ VIR_INFO("CPU hotplug netlink handler has been removed.");
+}
+
#define MAX_LISTEN 5
int main(int argc, char **argv) {
virNetServerPtr srv = NULL;
@@ -954,6 +993,7 @@ int main(int argc, char **argv) {
bool implicit_conf = false;
char *run_dir = NULL;
mode_t old_umask;
+ virCgroupPtr rootgrp = NULL;
struct option opts[] = {
{ "verbose", no_argument, &verbose, 1},
@@ -1327,11 +1367,32 @@ int main(int argc, char **argv) {
#endif
#if defined(__linux__) && defined(NETLINK_KOBJECT_UEVENT)
+ /**
+ * If we had ever missed any cpu hotplug event, we need to update
+ * cpuset.cpus to the lastest value
+ */
+ if (virCgroupAppRoot(privileged, &rootgrp, 0) != 0 ||
+ virHotplugSetCpusetToLastest(rootgrp) < 0) {
+ ret = VIR_DAEMON_ERR_INIT;
+ goto cleanup;
+ }
+
/* Register the netlink event service for NETLINK_KOBJECT_UEVENT */
if (virNetlinkEventServiceStart(NETLINK_KOBJECT_UEVENT, 1) < 0) {
ret = VIR_DAEMON_ERR_NETWORK;
goto cleanup;
}
+
+ /* Register cpu hotplug event handler for libvirtd */
+ if (virNetlinkEventServiceIsRunning(NETLINK_KOBJECT_UEVENT)) {
+ if (virNetlinkEventAddClient(daemonNetlinkCpuHotplugHandleCallback,
+ daemonNetlinkCpuHotplugRemoveCallback,
+ rootgrp, NULL,
+ NETLINK_KOBJECT_UEVENT) < 0) {
+ ret = VIR_DAEMON_ERR_NETWORK;
+ goto cleanup;
+ }
+ }
#endif
/* Run event loop. */
@@ -1362,6 +1423,7 @@ cleanup:
if (pid_file_fd != -1)
virPidFileReleasePath(pid_file, pid_file_fd);
+ virCgroupFree(&rootgrp);
VIR_FREE(sock_file);
VIR_FREE(sock_file_ro);
VIR_FREE(pid_file);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 2ff7e0e..752e3b0 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -64,6 +64,7 @@ virCgroupAddTaskController;
virCgroupAllowDevice;
virCgroupAllowDeviceMajor;
virCgroupAllowDevicePath;
+virCgroupAppRoot;
virCgroupControllerTypeFromString;
virCgroupControllerTypeToString;
virCgroupDenyAllDevices;
diff --git a/src/util/cgroup.c b/src/util/cgroup.c
index 393d439..a1b21de 100644
--- a/src/util/cgroup.c
+++ b/src/util/cgroup.c
@@ -641,9 +641,9 @@ err:
return rc;
}
-static int virCgroupAppRoot(int privileged,
- virCgroupPtr *group,
- int create)
+int virCgroupAppRoot(int privileged,
+ virCgroupPtr *group,
+ int create)
{
virCgroupPtr rootgrp = NULL;
int rc;
diff --git a/src/util/cgroup.h b/src/util/cgroup.h
index e294495..f31346c 100644
--- a/src/util/cgroup.h
+++ b/src/util/cgroup.h
@@ -44,6 +44,10 @@ enum {
VIR_ENUM_DECL(virCgroupController);
+int virCgroupAppRoot(int privileged,
+ virCgroupPtr *group,
+ int create);
+
int virCgroupForDriver(const char *name,
virCgroupPtr *group,
int privileged,
--
1.7.10.1