aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2010-02-26 01:34:51 -0500
committerDavid S. Miller <davem@davemloft.net>2010-02-27 05:43:39 -0500
commita2835763e130c343ace5320c20d33c281e7097b7 (patch)
tree26077aa8aec7a61fd7e3de31c5eeec4960f78079
parent10de05afe01c12cedc42eb9ce05b111eed6c8210 (diff)
rtnetlink: handle rtnl_link netlink notifications manually
In order to support specifying device flags during device creation, we must be able to roll back device registration in case setting the flags fails without sending any notifications related to the device to userspace. This patch changes rollback_registered_many() and register_netdevice() to manually send netlink notifications for devices not handled by rtnl_link and allows to defer notifications for devices handled by rtnl_link until setup is complete. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/netdevice.h7
-rw-r--r--net/core/dev.c8
-rw-r--r--net/core/rtnetlink.c4
3 files changed, 14 insertions, 5 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 7a2aea56f195..1bfda90c2625 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -924,7 +924,12 @@ struct net_device {
924 NETREG_UNREGISTERED, /* completed unregister todo */ 924 NETREG_UNREGISTERED, /* completed unregister todo */
925 NETREG_RELEASED, /* called free_netdev */ 925 NETREG_RELEASED, /* called free_netdev */
926 NETREG_DUMMY, /* dummy device for NAPI poll */ 926 NETREG_DUMMY, /* dummy device for NAPI poll */
927 } reg_state; 927 } reg_state:16;
928
929 enum {
930 RTNL_LINK_INITIALIZED,
931 RTNL_LINK_INITIALIZING,
932 } rtnl_link_state:16;
928 933
929 /* Called from unregister, can be used to call free_netdev */ 934 /* Called from unregister, can be used to call free_netdev */
930 void (*destructor)(struct net_device *dev); 935 void (*destructor)(struct net_device *dev);
diff --git a/net/core/dev.c b/net/core/dev.c
index eb7f1a4fefc6..75332b089529 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4865,6 +4865,10 @@ static void rollback_registered_many(struct list_head *head)
4865 */ 4865 */
4866 call_netdevice_notifiers(NETDEV_UNREGISTER, dev); 4866 call_netdevice_notifiers(NETDEV_UNREGISTER, dev);
4867 4867
4868 if (!dev->rtnl_link_ops ||
4869 dev->rtnl_link_state == RTNL_LINK_INITIALIZED)
4870 rtmsg_ifinfo(RTM_DELLINK, dev, ~0U);
4871
4868 /* 4872 /*
4869 * Flush the unicast and multicast chains 4873 * Flush the unicast and multicast chains
4870 */ 4874 */
@@ -5091,7 +5095,9 @@ int register_netdevice(struct net_device *dev)
5091 * Prevent userspace races by waiting until the network 5095 * Prevent userspace races by waiting until the network
5092 * device is fully setup before sending notifications. 5096 * device is fully setup before sending notifications.
5093 */ 5097 */
5094 rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U); 5098 if (!dev->rtnl_link_ops ||
5099 dev->rtnl_link_state == RTNL_LINK_INITIALIZED)
5100 rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U);
5095 5101
5096out: 5102out:
5097 return ret; 5103 return ret;
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index b7c7dfd86507..020e43bfef5f 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1425,9 +1425,6 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi
1425 struct net_device *dev = ptr; 1425 struct net_device *dev = ptr;
1426 1426
1427 switch (event) { 1427 switch (event) {
1428 case NETDEV_UNREGISTER:
1429 rtmsg_ifinfo(RTM_DELLINK, dev, ~0U);
1430 break;
1431 case NETDEV_UP: 1428 case NETDEV_UP:
1432 case NETDEV_DOWN: 1429 case NETDEV_DOWN:
1433 rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING); 1430 rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING);
@@ -1437,6 +1434,7 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi
1437 case NETDEV_REGISTER: 1434 case NETDEV_REGISTER:
1438 case NETDEV_CHANGE: 1435 case NETDEV_CHANGE:
1439 case NETDEV_GOING_DOWN: 1436 case NETDEV_GOING_DOWN:
1437 case NETDEV_UNREGISTER:
1440 case NETDEV_UNREGISTER_BATCH: 1438 case NETDEV_UNREGISTER_BATCH:
1441 break; 1439 break;
1442 default: 1440 default: