[libvirt] [PATCH alternative 2] util: fix libvirtd startup failure due to netlink error

Laine Stump laine at laine.org
Tue May 1 19:11:06 UTC 2012


This is an alternate method of solving the problem detailed in:

  https://bugzilla.redhat.com/show_bug.cgi?id=816465

Testing has shown that if we "reserve" the bind address of "pid of
libvirtd" so that libnl never tries to bind it, our bind of "pid of
libnl + (1 << 22)" (which is what libnl ends up using for the 2nd
socket it binds) will *always* succeed the first time. The way to make
this reservation is to allocate a handle from libnl (it internally
assigns the address it will use at handle alloc time), then just never
use that handle - it is a place holder for whatever other code in the
process is using netlink sockets directly (i.e. not through libnl).

The advantage of this patch over the other is that it doesn't rely on
timing at all.

The disadvantage (?maybe? maybe not, I'm not sure - someone more
knowledgeable about the libvirtd<->lldpad communication please inform)
is that the bind address used by the netlink socket that communicates
with lldpad will be "pid of libvirtd + (1 << 22)", not "pid of
libvirtd".
---
 src/util/virnetlink.c |   25 +++++++++++++++++++++----
 1 file changed, 21 insertions(+), 4 deletions(-)

diff --git a/src/util/virnetlink.c b/src/util/virnetlink.c
index b2e9d51..aca0c07 100644
--- a/src/util/virnetlink.c
+++ b/src/util/virnetlink.c
@@ -68,6 +68,7 @@ struct _virNetlinkEventSrvPrivate {
     int eventwatch;
     int netlinkfd;
     struct nl_handle *netlinknh;
+    struct nl_handle *dummy_netlinknh;
     /*Events*/
     int handled;
     size_t handlesCount;
@@ -286,6 +287,7 @@ virNetlinkEventServiceStop(void)
     virNetlinkEventServerLock(srv);
     nl_close(srv->netlinknh);
     nl_handle_destroy(srv->netlinknh);
+    nl_handle_destroy(srv->dummy_netlinknh);
     virEventRemoveHandle(srv->eventwatch);
 
     /* free any remaining clients on the list */
@@ -345,13 +347,24 @@ virNetlinkEventServiceStart(void)
 
     virNetlinkEventServerLock(srv);
 
+    srv->netlinknh = NULL;
+    /* Allocate a dummy nl_handle to reserve the address "pid of
+     * libvirtd" for whatever library is using it.
+     */
+    srv->dummy_netlinknh = nl_handle_alloc();
+    if (!srv->dummy_netlinknh) {
+        virReportSystemError(errno, "%s",
+                             _("cannot allocate space holder nlhandle for virNetlinkEvent server"));
+        goto error_server;
+    }
+
     /* Allocate a new socket and get fd */
     srv->netlinknh = nl_handle_alloc();
 
     if (!srv->netlinknh) {
         virReportSystemError(errno,
                              "%s", _("cannot allocate nlhandle for virNetlinkEvent server"));
-        goto error_locked;
+        goto error_server;
     }
 
     if (nl_connect(srv->netlinknh, NETLINK_ROUTE) < 0) {
@@ -391,10 +404,14 @@ virNetlinkEventServiceStart(void)
 
 error_server:
     if (ret < 0) {
-        nl_close(srv->netlinknh);
-        nl_handle_destroy(srv->netlinknh);
+        if (srv->netlinknh) {
+            nl_close(srv->netlinknh);
+            nl_handle_destroy(srv->netlinknh);
+        }
+        if (srv->dummy_netlinknh) {
+            nl_handle_destroy(srv->dummy_netlinknh);
+        }
     }
-error_locked:
     virNetlinkEventServerUnlock(srv);
     if (ret < 0) {
         virMutexDestroy(&srv->lock);
-- 
1.7.10




More information about the libvir-list mailing list