Skip to content

Commit

Permalink
rtnetlink: handle rtnl_link netlink notifications manually
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Patrick McHardy authored and David S. Miller committed Feb 27, 2010
1 parent 10de05a commit a283576
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 5 deletions.
7 changes: 6 additions & 1 deletion include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -924,7 +924,12 @@ struct net_device {
NETREG_UNREGISTERED, /* completed unregister todo */
NETREG_RELEASED, /* called free_netdev */
NETREG_DUMMY, /* dummy device for NAPI poll */
} reg_state;
} reg_state:16;

enum {
RTNL_LINK_INITIALIZED,
RTNL_LINK_INITIALIZING,
} rtnl_link_state:16;

/* Called from unregister, can be used to call free_netdev */
void (*destructor)(struct net_device *dev);
Expand Down
8 changes: 7 additions & 1 deletion net/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -4865,6 +4865,10 @@ static void rollback_registered_many(struct list_head *head)
*/
call_netdevice_notifiers(NETDEV_UNREGISTER, dev);

if (!dev->rtnl_link_ops ||
dev->rtnl_link_state == RTNL_LINK_INITIALIZED)
rtmsg_ifinfo(RTM_DELLINK, dev, ~0U);

/*
* Flush the unicast and multicast chains
*/
Expand Down Expand Up @@ -5091,7 +5095,9 @@ int register_netdevice(struct net_device *dev)
* Prevent userspace races by waiting until the network
* device is fully setup before sending notifications.
*/
rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U);
if (!dev->rtnl_link_ops ||
dev->rtnl_link_state == RTNL_LINK_INITIALIZED)
rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U);

out:
return ret;
Expand Down
4 changes: 1 addition & 3 deletions net/core/rtnetlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -1425,9 +1425,6 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi
struct net_device *dev = ptr;

switch (event) {
case NETDEV_UNREGISTER:
rtmsg_ifinfo(RTM_DELLINK, dev, ~0U);
break;
case NETDEV_UP:
case NETDEV_DOWN:
rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING);
Expand All @@ -1437,6 +1434,7 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi
case NETDEV_REGISTER:
case NETDEV_CHANGE:
case NETDEV_GOING_DOWN:
case NETDEV_UNREGISTER:
case NETDEV_UNREGISTER_BATCH:
break;
default:
Expand Down

0 comments on commit a283576

Please sign in to comment.