networkd: netdev - avoid hanging transactions in failure cases

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.
This commit is contained in:
Tom Gundersen 2015-06-29 14:24:40 +02:00
parent b024a9cfb1
commit 62e2d5bbab
2 changed files with 12 additions and 2 deletions

View 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;

View 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;