Message ID | 1453896850-22775-1-git-send-email-johannes@sipsolutions.net (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Johannes Berg |
Headers | show |
On Wed, 2016-01-27 at 13:14 +0100, Johannes Berg wrote: > > +static int wext_netdev_notifier_call(struct notifier_block *nb, > + unsigned long state, void *ptr) > +{ > + /* > + * When a netdev is unregistered, flush all pending messages > + * to avoid them going out after the RTM_DELLINK, which can > + * happen due to the schedule_work(). > + */ > + if (state == NETDEV_UNREGISTER) > + wireless_nlevent_flush(); > It could be argued that the state check isn't really necessary and should be removed to avoid ordering issues with up/down vs. wext, but this fixes the really strange issue where you get an RTM_NEWLINK after RTM_DELLINK (with the same ifidx), and I don't see how any software would care much about the ordering otherwise. johannes -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
> > + if (state == NETDEV_UNREGISTER) > > + wireless_nlevent_flush(); > > > It could be argued that the state check isn't really necessary and > should be removed to avoid ordering issues with up/down vs. wext, but > this fixes the really strange issue where you get an RTM_NEWLINK > after > RTM_DELLINK (with the same ifidx), and I don't see how any software > would care much about the ordering otherwise. > Actually though, with the fix I still get: 5: wlan1: <BROADCAST,MULTICAST> mtu 1500 qdisc mq state DOWN group default link/ether 02:00:00:00:01:00 brd ff:ff:ff:ff:ff:ff 5: wlan1: <BROADCAST,MULTICAST,UP> link/ether Deleted 5: wlan1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default link/ether 02:00:00:00:01:00 brd ff:ff:ff:ff:ff:ff which is clearly odd (see the UP flag), so I'll change it. johannes -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Wed, 2016-01-27 at 13:18 +0100, Johannes Berg wrote: > > > + if (state == NETDEV_UNREGISTER) > > > + wireless_nlevent_flush(); > > > > > It could be argued that the state check isn't really necessary and > > should be removed to avoid ordering issues with up/down vs. wext, > > but > > this fixes the really strange issue where you get an RTM_NEWLINK > > after > > RTM_DELLINK (with the same ifidx), and I don't see how any software > > would care much about the ordering otherwise. > > > > Actually though, with the fix I still get: > > 5: wlan1: <BROADCAST,MULTICAST> mtu 1500 qdisc mq state DOWN group > default > link/ether 02:00:00:00:01:00 brd ff:ff:ff:ff:ff:ff > 5: wlan1: <BROADCAST,MULTICAST,UP> > link/ether > Deleted 5: wlan1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state > DOWN group default > link/ether 02:00:00:00:01:00 brd ff:ff:ff:ff:ff:ff > > which is clearly odd (see the UP flag), so I'll change it. > Doesn't help, since the wext netdev notifier is registered earlier and thus runs earlier than the cfg80211 one that triggers the action ... I'll fix that differently then. johannes -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c index c8717c1d082e..4e4e1c5236cc 100644 --- a/net/wireless/wext-core.c +++ b/net/wireless/wext-core.c @@ -342,6 +342,38 @@ static const int compat_event_type_size[] = { /* IW event code */ +static void wireless_nlevent_flush(void) +{ + struct sk_buff *skb; + struct net *net; + + ASSERT_RTNL(); + + for_each_net(net) { + while ((skb = skb_dequeue(&net->wext_nlevents))) + rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, + GFP_KERNEL); + } +} + +static int wext_netdev_notifier_call(struct notifier_block *nb, + unsigned long state, void *ptr) +{ + /* + * When a netdev is unregistered, flush all pending messages + * to avoid them going out after the RTM_DELLINK, which can + * happen due to the schedule_work(). + */ + if (state == NETDEV_UNREGISTER) + wireless_nlevent_flush(); + + return NOTIFY_OK; +} + +static struct notifier_block wext_netdev_notifier = { + .notifier_call = wext_netdev_notifier_call, +}; + static int __net_init wext_pernet_init(struct net *net) { skb_queue_head_init(&net->wext_nlevents); @@ -360,6 +392,11 @@ static struct pernet_operations wext_pernet_ops = { static int __init wireless_nlevent_init(void) { + int err = register_netdevice_notifier(&wext_netdev_notifier); + + if (err) + return err; + return register_pernet_subsys(&wext_pernet_ops); } @@ -368,17 +405,8 @@ subsys_initcall(wireless_nlevent_init); /* Process events generated by the wireless layer or the driver. */ static void wireless_nlevent_process(struct work_struct *work) { - struct sk_buff *skb; - struct net *net; - rtnl_lock(); - - for_each_net(net) { - while ((skb = skb_dequeue(&net->wext_nlevents))) - rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, - GFP_KERNEL); - } - + wireless_nlevent_flush(); rtnl_unlock(); }