macvlan: remove one synchronize_rcu() call
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>
This commit is contained in:
parent
034cfe48d0
commit
449f454426
|
@ -70,16 +70,17 @@ static void macvlan_hash_add(struct macvlan_dev *vlan)
|
|||
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);
|
||||
synchronize_rcu();
|
||||
if (sync)
|
||||
synchronize_rcu();
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
|
@ -345,7 +346,7 @@ static int macvlan_stop(struct net_device *dev)
|
|||
dev_uc_del(lowerdev, dev->dev_addr);
|
||||
|
||||
hash_del:
|
||||
macvlan_hash_del(vlan);
|
||||
macvlan_hash_del(vlan, !dev->dismantle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1293,7 +1293,9 @@ struct net_device {
|
|||
NETREG_UNREGISTERED, /* completed unregister todo */
|
||||
NETREG_RELEASED, /* called free_netdev */
|
||||
NETREG_DUMMY, /* dummy device for NAPI poll */
|
||||
} reg_state:16;
|
||||
} reg_state:8;
|
||||
|
||||
bool dismantle; /* device is going do be freed */
|
||||
|
||||
enum {
|
||||
RTNL_LINK_INITIALIZED,
|
||||
|
|
|
@ -5126,7 +5126,7 @@ static void rollback_registered_many(struct list_head *head)
|
|||
list_del(&dev->unreg_list);
|
||||
continue;
|
||||
}
|
||||
|
||||
dev->dismantle = true;
|
||||
BUG_ON(dev->reg_state != NETREG_REGISTERED);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue