When one macvlan device is dismantled, we can avoid one
synchronize_rcu() call done after deletion from hash list, since caller
will perform a synchronize_net() call after its ndo_stop() call.
Add a new netdev->dismantle field to signal this dismantle intent.
Reduces RTNL hold time.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
CC: Patrick McHardy <kaber@trash.net>
CC: Ben Greear <greearb@candelatech.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
hlist_add_head_rcu(&vlan->hlist, &port->vlan_hash[addr[5]]);
}
hlist_add_head_rcu(&vlan->hlist, &port->vlan_hash[addr[5]]);
}
-static void macvlan_hash_del(struct macvlan_dev *vlan)
+static void macvlan_hash_del(struct macvlan_dev *vlan, bool sync)
{
hlist_del_rcu(&vlan->hlist);
{
hlist_del_rcu(&vlan->hlist);
+ if (sync)
+ synchronize_rcu();
}
static void macvlan_hash_change_addr(struct macvlan_dev *vlan,
const unsigned char *addr)
{
}
static void macvlan_hash_change_addr(struct macvlan_dev *vlan,
const unsigned char *addr)
{
- macvlan_hash_del(vlan);
+ macvlan_hash_del(vlan, true);
/* Now that we are unhashed it is safe to change the device
* address without confusing packet delivery.
*/
/* Now that we are unhashed it is safe to change the device
* address without confusing packet delivery.
*/
dev_uc_del(lowerdev, dev->dev_addr);
hash_del:
dev_uc_del(lowerdev, dev->dev_addr);
hash_del:
- macvlan_hash_del(vlan);
+ macvlan_hash_del(vlan, !dev->dismantle);
NETREG_UNREGISTERED, /* completed unregister todo */
NETREG_RELEASED, /* called free_netdev */
NETREG_DUMMY, /* dummy device for NAPI poll */
NETREG_UNREGISTERED, /* completed unregister todo */
NETREG_RELEASED, /* called free_netdev */
NETREG_DUMMY, /* dummy device for NAPI poll */
+ } reg_state:8;
+
+ bool dismantle; /* device is going do be freed */
enum {
RTNL_LINK_INITIALIZED,
enum {
RTNL_LINK_INITIALIZED,
list_del(&dev->unreg_list);
continue;
}
list_del(&dev->unreg_list);
continue;
}
BUG_ON(dev->reg_state != NETREG_REGISTERED);
}
BUG_ON(dev->reg_state != NETREG_REGISTERED);
}