chiark / gitweb /
networkd: link - improve refcounting
authorTom Gundersen <teg@jklm.no>
Tue, 1 Jul 2014 08:09:52 +0000 (10:09 +0200)
committerTom Gundersen <teg@jklm.no>
Tue, 1 Jul 2014 08:21:18 +0000 (10:21 +0200)
We failed to take a ref when waiting for udev synchronization. Fix that and also
make unreffing in callbacks simpler throughout by using _cleanup_ macros.

Fixes <https://bugs.freedesktop.org/show_bug.cgi?id=80556>.

src/network/networkd-link.c
src/network/networkd-manager.c

index 8df7ff5d606ca9a98cb810acd25242892fa3cc40..c99cafc24bfb409f34ac2aef04ee07739d2bcde4 100644 (file)
@@ -366,7 +366,7 @@ static int link_enter_configured(Link *link) {
 }
 
 static int route_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
-        Link *link = userdata;
+        _cleanup_link_unref_ Link *link = userdata;
         int r;
 
         assert(link->route_messages > 0);
@@ -376,10 +376,8 @@ static int route_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
 
         link->route_messages --;
 
-        if (IN_SET(LINK_STATE_FAILED, LINK_STATE_LINGER)) {
-                link_unref(link);
+        if (IN_SET(LINK_STATE_FAILED, LINK_STATE_LINGER))
                 return 1;
-        }
 
         r = sd_rtnl_message_get_errno(m);
         if (r < 0 && r != -EEXIST)
@@ -397,8 +395,6 @@ static int route_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
                 link_enter_configured(link);
         }
 
-        link_unref(link);
-
         return 1;
 }
 
@@ -586,17 +582,15 @@ static int link_enter_set_routes(Link *link) {
 }
 
 static int route_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
-        Link *link = userdata;
+        _cleanup_link_unref_ Link *link = userdata;
         int r;
 
         assert(m);
         assert(link);
         assert(link->ifname);
 
-        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) {
-                link_unref(link);
+        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
                 return 1;
-        }
 
         r = sd_rtnl_message_get_errno(m);
         if (r < 0 && r != -ESRCH)
@@ -607,13 +601,11 @@ static int route_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata)
                                 "ERRNO=%d", -r,
                                 NULL);
 
-        link_unref(link);
-
         return 0;
 }
 
 static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
-        Link *link = userdata;
+        _cleanup_link_unref_ Link *link = userdata;
         int r;
 
         assert(m);
@@ -625,10 +617,8 @@ static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
 
         link->addr_messages --;
 
-        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) {
-                link_unref(link);
+        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
                 return 1;
-        }
 
         r = sd_rtnl_message_get_errno(m);
         if (r < 0 && r != -EEXIST)
@@ -644,8 +634,6 @@ static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
                 link_enter_set_routes(link);
         }
 
-        link_unref(link);
-
         return 1;
 }
 
@@ -780,17 +768,15 @@ static int link_enter_set_addresses(Link *link) {
 }
 
 static int address_update_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
-        Link *link = userdata;
+        _cleanup_link_unref_ Link *link = userdata;
         int r;
 
         assert(m);
         assert(link);
         assert(link->ifname);
 
-        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) {
-                link_unref(link);
+        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
                 return 1;
-        }
 
         r = sd_rtnl_message_get_errno(m);
         if (r < 0 && r != -ENOENT)
@@ -801,23 +787,19 @@ static int address_update_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userd
                                 "ERRNO=%d", -r,
                                 NULL);
 
-        link_unref(link);
-
         return 0;
 }
 
 static int address_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
-        Link *link = userdata;
+        _cleanup_link_unref_ Link *link = userdata;
         int r;
 
         assert(m);
         assert(link);
         assert(link->ifname);
 
-        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) {
-                link_unref(link);
+        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
                 return 1;
-        }
 
         r = sd_rtnl_message_get_errno(m);
         if (r < 0 && r != -EADDRNOTAVAIL)
@@ -828,28 +810,22 @@ static int address_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdat
                                 "ERRNO=%d", -r,
                                 NULL);
 
-        link_unref(link);
-
         return 0;
 }
 
 static int set_hostname_handler(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
-        Link *link = userdata;
+        _cleanup_link_unref_ Link *link = userdata;
         int r;
 
         assert(link);
 
-        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) {
-                link_unref(link);
+        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
                 return 1;
-        }
 
         r = sd_bus_message_get_errno(m);
         if (r < 0)
                 log_warning_link(link, "Could not set hostname: %s", strerror(-r));
 
-        link_unref(link);
-
         return 1;
 }
 
@@ -883,26 +859,26 @@ static int link_set_hostname(Link *link, const char *hostname) {
                 return r;
 
         r = sd_bus_call_async(link->manager->bus, NULL, m, set_hostname_handler, link, 0);
-        if (r < 0)
+        if (r < 0) {
                 log_error_link(link, "Could not set transient hostname: %s", strerror(-r));
+                return r;
+        }
 
         link_ref(link);
 
-        return r;
+        return 0;
 }
 
 static int set_mtu_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
-        Link *link = userdata;
+        _cleanup_link_unref_ Link *link = userdata;
         int r;
 
         assert(m);
         assert(link);
         assert(link->ifname);
 
-        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) {
-                link_unref(link);
+        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
                 return 1;
-        }
 
         r = sd_rtnl_message_get_errno(m);
         if (r < 0)
@@ -912,8 +888,6 @@ static int set_mtu_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
                                 "ERRNO=%d", -r,
                                 NULL);
 
-        link_unref(link);
-
         return 1;
 }
 
@@ -1685,15 +1659,13 @@ static int link_update_flags(Link *link, sd_rtnl_message *m) {
 }
 
 static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
-        Link *link = userdata;
+        _cleanup_link_unref_ Link *link = userdata;
         int r;
 
         assert(link);
 
-        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) {
-                link_unref(link);
+        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
                 return 1;
-        }
 
         r = sd_rtnl_message_get_errno(m);
         if (r < 0) {
@@ -1707,8 +1679,6 @@ static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
                                 NULL);
         }
 
-        link_unref(link);
-
         return 1;
 }
 
@@ -1766,7 +1736,7 @@ static int link_enslaved(Link *link) {
 }
 
 static int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
-        Link *link = userdata;
+        _cleanup_link_unref_ Link *link = userdata;
         int r;
 
         assert(link);
@@ -1776,10 +1746,8 @@ static int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
 
         link->enslaving --;
 
-        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) {
-                link_unref(link);
+        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
                 return 1;
-        }
 
         r = sd_rtnl_message_get_errno(m);
         if (r < 0) {
@@ -1790,7 +1758,6 @@ static int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
                                 "ERRNO=%d", -r,
                                 NULL);
                 link_enter_failed(link);
-                link_unref(link);
                 return 1;
         }
 
@@ -1799,8 +1766,6 @@ static int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
         if (link->enslaving == 0)
                 link_enslaved(link);
 
-        link_unref(link);
-
         return 1;
 }
 
@@ -2084,7 +2049,7 @@ static int link_configure(Link *link) {
 }
 
 static int link_initialized_and_synced(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
-        Link *link = userdata;
+        _cleanup_link_unref_ Link *link = userdata;
         Network *network;
         int r;
 
@@ -2093,14 +2058,14 @@ static int link_initialized_and_synced(sd_rtnl *rtnl, sd_rtnl_message *m, void *
         assert(link->manager);
 
         if (link->state != LINK_STATE_INITIALIZING)
-                return 0;
+                return 1;
 
         log_debug_link(link, "link state is up-to-date");
 
         r = network_get(link->manager, link->udev_device, link->ifname, &link->mac, &network);
         if (r == -ENOENT) {
                 link_enter_unmanaged(link);
-                return 0;
+                return 1;
         } else if (r < 0)
                 return r;
 
@@ -2112,7 +2077,7 @@ static int link_initialized_and_synced(sd_rtnl *rtnl, sd_rtnl_message *m, void *
         if (r < 0)
                 return r;
 
-        return 0;
+        return 1;
 }
 
 int link_initialized(Link *link, struct udev_device *device) {
@@ -2144,6 +2109,8 @@ int link_initialized(Link *link, struct udev_device *device) {
         if (r < 0)
                 return r;
 
+        link_ref(link);
+
         return 0;
 }
 
@@ -2270,12 +2237,13 @@ int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, void *use
 }
 
 static int link_get_address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
-        Link *link = userdata;
+        _cleanup_link_unref_ Link *link = userdata;
         int r;
 
         assert(rtnl);
         assert(m);
         assert(link);
+        assert(link->manager);
 
         for (; m; m = sd_rtnl_message_next(m)) {
                 r = sd_rtnl_message_get_errno(m);
@@ -2320,6 +2288,8 @@ int link_add(Manager *m, sd_rtnl_message *message, Link **ret) {
         if (r < 0)
                 return r;
 
+        link_ref(link);
+
         if (detect_container(NULL) <= 0) {
                 /* not in a container, udev will be around */
                 sprintf(ifindex_str, "n%"PRIu64, link->ifindex);
@@ -2339,6 +2309,9 @@ int link_add(Manager *m, sd_rtnl_message *message, Link **ret) {
                 if (r < 0)
                         return r;
         } else {
+                /* we are calling a callback directly, so must take a ref */
+                link_ref(link);
+
                 r = link_initialized_and_synced(m->rtnl, NULL, link);
                 if (r < 0)
                         return r;
index 5cc88723e5215265ad0dc98638fc2483fb4ecd20..c93d598c6bbc4a664d0f72c2f9c5ed16d4319f58 100644 (file)
@@ -410,6 +410,8 @@ int manager_udev_listen(Manager *m) {
 int manager_rtnl_listen(Manager *m) {
         int r;
 
+        assert(m);
+
         r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
         if (r < 0)
                 return r;