Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 395264d5 authored by Octavian Purdila's avatar Octavian Purdila Committed by David S. Miller
Browse files

net: introduce NETDEV_UNREGISTER_PERNET



This new event is called once for each unique net namespace in batched
unregister operations (with the argument set to a random device from
that namespace) and once per device in non-batched unregister
operations.

It allows us to factorize some device unregister work such as clearing the
routing cache.

Signed-off-by: default avatarOctavian Purdila <opurdila@ixiacom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent fccaf710
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -202,6 +202,7 @@ static inline int notifier_to_errno(int ret)
#define NETDEV_BONDING_OLDTYPE  0x000E
#define NETDEV_BONDING_NEWTYPE  0x000F
#define NETDEV_POST_INIT	0x0010
#define NETDEV_UNREGISTER_PERNET 0x0011

#define SYS_DOWN	0x0001	/* Notify of system down */
#define SYS_RESTART	SYS_DOWN
+27 −2
Original line number Diff line number Diff line
@@ -1344,6 +1344,7 @@ int register_netdevice_notifier(struct notifier_block *nb)
				nb->notifier_call(nb, NETDEV_DOWN, dev);
			}
			nb->notifier_call(nb, NETDEV_UNREGISTER, dev);
			nb->notifier_call(nb, NETDEV_UNREGISTER_PERNET, dev);
		}
	}

@@ -4721,7 +4722,8 @@ static void net_set_todo(struct net_device *dev)

static void rollback_registered_many(struct list_head *head)
{
	struct net_device *dev;
	struct net_device *dev, *aux, *fdev;
	LIST_HEAD(pernet_list);

	BUG_ON(dev_boot_phase);
	ASSERT_RTNL();
@@ -4779,8 +4781,24 @@ static void rollback_registered_many(struct list_head *head)

	synchronize_net();

	list_for_each_entry(dev, head, unreg_list)
	list_for_each_entry_safe(dev, aux, head, unreg_list) {
		int new_net = 1;
		list_for_each_entry(fdev, &pernet_list, unreg_list) {
			if (dev_net(dev) == dev_net(fdev)) {
				new_net = 0;
				dev_put(dev);
				break;
			}
		}
		if (new_net)
			list_move(&dev->unreg_list, &pernet_list);
	}

	list_for_each_entry_safe(dev, aux, &pernet_list, unreg_list) {
		call_netdevice_notifiers(NETDEV_UNREGISTER_PERNET, dev);
		list_move(&dev->unreg_list, head);
		dev_put(dev);
	}
}

static void rollback_registered(struct net_device *dev)
@@ -5074,6 +5092,8 @@ static void netdev_wait_allrefs(struct net_device *dev)

			/* Rebroadcast unregister notification */
			call_netdevice_notifiers(NETDEV_UNREGISTER, dev);
			/* don't resend NETDEV_UNREGISTER_PERNET, _PERNET users
			 * should have already handle it the first time */

			if (test_bit(__LINK_STATE_LINKWATCH_PENDING,
				     &dev->state)) {
@@ -5385,6 +5405,10 @@ EXPORT_SYMBOL(unregister_netdevice_queue);
 *	unregister_netdevice_many - unregister many devices
 *	@head: list of devices
 *
 *	WARNING: Calling this modifies the given list
 *	(in rollback_registered_many). It may change the order of the elements
 *	in the list. However, you can assume it does not add or delete elements
 *	to/from the list.
 */
void unregister_netdevice_many(struct list_head *head)
{
@@ -5504,6 +5528,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
	   this device. They should clean all the things.
	*/
	call_netdevice_notifiers(NETDEV_UNREGISTER, dev);
	call_netdevice_notifiers(NETDEV_UNREGISTER_PERNET, dev);

	/*
	 *	Flush the unicast and multicast chains