[libvirt] [RFC] [PATCH] Support for uevent netlink and hotplug event.

tangchen tangchen at cn.fujitsu.com
Wed Jul 18 12:22:05 UTC 2012


NOTE: This patch is just for some comments, so that we can try to
      improve netlink support in libvirt.

This patch introduces a new global array servers[MAX_LINKS],
and all the netlink protocol (at most 32 protocols)
can be supportted.

And also, it creates a NETLINK_KOBJECT_UEVENT socket to listen
to hotplug events.

Signed-off-by: Tang Chen <tangchen at cn.fujitsu.com>
---
 src/libvirt_private.syms |    1 +
 src/util/virnetlink.c    |  103 ++++++++++++++++++++++++++++++++++++++++++++++
 src/util/virnetlink.h    |    5 +++
 3 files changed, 109 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 7373281..0ef21d9 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1378,6 +1378,7 @@ virNetlinkEventServiceIsRunning;
 virNetlinkEventServiceLocalPid;
 virNetlinkEventServiceStop;
 virNetlinkEventServiceStart;
+virNetlinkEventServiceStartProtocol;
 virNetlinkShutdown;
 virNetlinkStartup;
 
diff --git a/src/util/virnetlink.c b/src/util/virnetlink.c
index bb0dae9..489c149 100644
--- a/src/util/virnetlink.c
+++ b/src/util/virnetlink.c
@@ -98,6 +98,7 @@ static int nextWatch = 1;
 # define NETLINK_EVENT_ALLOC_EXTENT 10
 
 static virNetlinkEventSrvPrivatePtr server = NULL;
+static virNetlinkEventSrvPrivatePtr servers[MAX_LINKS] = {NULL};
 static virNetlinkHandle *placeholder_nlhandle = NULL;
 
 /* Function definitions */
@@ -307,6 +308,8 @@ virNetlinkEventCallback(int watch,
         return;
     }
 
+    VIR_INFO("%s", msg);
+
     virNetlinkEventServerLock(srv);
 
     VIR_DEBUG("dispatching to max %d clients, called from event watch %d",
@@ -398,6 +401,106 @@ int virNetlinkEventServiceLocalPid(void)
 
 
 /**
+ * virNetlinkEventServiceStartProtocol:
+ *
+ * start a monitor to receive netlink messages for libvirtd.
+ * This registers a netlink socket with the event interface.
+ *
+ * @protocol: netlink protocol
+ * @groups: broadcast groups to join
+ * Returns -1 if the monitor cannot be registered, 0 upon success
+ */
+int
+virNetlinkEventServiceStartProtocol(int protocol, int groups)
+{
+    virNetlinkEventSrvPrivatePtr srv;
+    int fd;
+    int ret = -1;
+
+    if (protocol < 0 || protocol >= MAX_LINKS ||
+	groups < 0 || groups >= 32) {
+	return -EINVAL;
+    }
+
+    if (servers[protocol])
+        return 0;
+
+    VIR_INFO("starting netlink event service with protocol %d", protocol);
+
+    if (VIR_ALLOC(srv) < 0) {
+        virReportOOMError();
+        return -1;
+    }
+
+    if (virMutexInit(&srv->lock) < 0) {
+        VIR_FREE(srv);
+        return -1;
+    }
+
+    virNetlinkEventServerLock(srv);
+
+    /* Allocate a new socket and get fd */
+    srv->netlinknh = virNetlinkAlloc();
+
+    if (!srv->netlinknh) {
+        virReportSystemError(errno,
+                             "%s", _("cannot allocate nlhandle for virNetlinkEvent server"));
+        goto error_locked;
+    }
+
+    nl_join_groups(srv->netlinknh, groups);
+
+    if (nl_connect(srv->netlinknh, protocol) < 0) {
+        virReportSystemError(errno,
+                             "%s", _("cannot connect to netlink socket"));
+        goto error_server;
+    }
+
+    fd = nl_socket_get_fd(srv->netlinknh);
+
+    if (fd < 0) {
+        virReportSystemError(errno,
+                             "%s", _("cannot get netlink socket fd"));
+        goto error_server;
+    }
+
+    if (nl_socket_set_nonblocking(srv->netlinknh)) {
+        virReportSystemError(errno, "%s",
+                             _("cannot set netlink socket nonblocking"));
+        goto error_server;
+    }
+
+    if ((srv->eventwatch = virEventAddHandle(fd,
+                                             VIR_EVENT_HANDLE_READABLE,
+                                             virNetlinkEventCallback,
+                                             srv, NULL)) < 0) {
+        netlinkError(VIR_ERR_INTERNAL_ERROR, "%s",
+                     _("Failed to add netlink event handle watch"));
+        goto error_server;
+    }
+
+    srv->netlinkfd = fd;
+    VIR_DEBUG("netlink event listener on fd: %i running", fd);
+
+    ret = 0;
+    servers[protocol] = srv;
+
+error_server:
+    if (ret < 0) {
+        nl_close(srv->netlinknh);
+        virNetlinkFree(srv->netlinknh);
+    }
+error_locked:
+    virNetlinkEventServerUnlock(srv);
+    if (ret < 0) {
+        virMutexDestroy(&srv->lock);
+        VIR_FREE(srv);
+    }
+    return ret;
+}
+
+
+/**
  * virNetlinkEventServiceStart:
  *
  * start a monitor to receive netlink messages for libvirtd.
diff --git a/src/util/virnetlink.h b/src/util/virnetlink.h
index 8ec27c9..256f129 100644
--- a/src/util/virnetlink.h
+++ b/src/util/virnetlink.h
@@ -59,6 +59,11 @@ int virNetlinkEventServiceStop(void);
 int virNetlinkEventServiceStart(void);
 
 /**
+ * startNetlinkEventServerProtocol: start a monitor with specified protocol to receive netlink messages for libvirtd
+ */
+int virNetlinkEventServiceStartProtocol(int protocol, int groups);
+
+/**
  * virNetlinkEventServiceIsRunning: returns if the netlink event service is running.
  */
 bool virNetlinkEventServiceIsRunning(void);
-- 
1.7.10.2




More information about the libvir-list mailing list