]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
networkd: netdev - avoid hanging transactions in failure cases 409/head
authorTom Gundersen <teg@jklm.no>
Mon, 29 Jun 2015 12:24:40 +0000 (14:24 +0200)
committerTom Gundersen <teg@jklm.no>
Mon, 29 Jun 2015 12:26:36 +0000 (14:26 +0200)
If a link is attempted t obe enslaved by a netdev that has already failed, we
must fail immediately and not save the callback for later, as it will then
never get triggered.

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

index 16243a53528285db9dd4d6c7f58b5a503837431c..dff81a5cf083972549371615bd2c424347c1dfb9 100644 (file)
@@ -1360,8 +1360,7 @@ static int link_joined(Link *link) {
         return link_enter_set_addresses(link);
 }
 
-static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m,
-                               void *userdata) {
+static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
         _cleanup_link_unref_ Link *link = userdata;
         int r;
 
index 73d3b6bf6c26bf2b10ef2bdd3b925238e38ccd8f..6949b403c8dd2b25bb418c8d80af90a852425d37 100644 (file)
@@ -96,6 +96,7 @@ static void netdev_cancel_callbacks(NetDev *netdev) {
                 }
 
                 LIST_REMOVE(callbacks, netdev->callbacks, callback);
+                link_unref(callback->link);
                 free(callback);
         }
 }
@@ -177,6 +178,8 @@ int netdev_get(Manager *manager, const char *name, NetDev **ret) {
 static int netdev_enter_failed(NetDev *netdev) {
         netdev->state = NETDEV_STATE_FAILED;
 
+        netdev_cancel_callbacks(netdev);
+
         return 0;
 }
 
@@ -266,12 +269,20 @@ int netdev_enslave(NetDev *netdev, Link *link, sd_netlink_message_handler_t call
         int r;
 
         assert(netdev);
+        assert(netdev->manager);
+        assert(netdev->manager->rtnl);
         assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND));
 
         if (netdev->state == NETDEV_STATE_READY) {
                 r = netdev_enslave_ready(netdev, link, callback);
                 if (r < 0)
                         return r;
+        } else if (IN_SET(netdev->state, NETDEV_STATE_LINGER, NETDEV_STATE_FAILED)) {
+                _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
+
+                r = rtnl_message_new_synthetic_error(-ENODEV, 0, &m);
+                if (r >= 0)
+                        callback(netdev->manager->rtnl, m, link);
         } else {
                 /* the netdev is not yet read, save this request for when it is */
                 netdev_join_callback *cb;