diff options
author | Stephen Hemminger <stephen@networkplumber.org> | 2013-06-17 14:16:11 -0700 |
---|---|---|
committer | Stephen Hemminger <stephen@networkplumber.org> | 2013-06-24 08:40:32 -0700 |
commit | ebf4063e869d959daf75efb4ef1c7bc80dcd4800 (patch) | |
tree | 2dc421d4770f6a3f9000f4e3136c5c96303ca6e0 /drivers | |
parent | 1c51a9159ddefa5119724a4c7da3fd3ef44b68d5 (diff) | |
download | linux-stable-ebf4063e869d959daf75efb4ef1c7bc80dcd4800.tar.gz linux-stable-ebf4063e869d959daf75efb4ef1c7bc80dcd4800.tar.bz2 linux-stable-ebf4063e869d959daf75efb4ef1c7bc80dcd4800.zip |
vxlan: move cleanup to uninit
Put destruction of per-cpu statistics removal in
ndo_uninit since it is created by ndo_init.
This also avoids any problems that might be cause by destructor
being called after module removed.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/vxlan.c | 24 |
1 files changed, 13 insertions, 11 deletions
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 71da8be98801..500f9ce437ec 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1256,6 +1256,17 @@ static int vxlan_init(struct net_device *dev) return 0; } +static void vxlan_uninit(struct net_device *dev) +{ + struct vxlan_dev *vxlan = netdev_priv(dev); + struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); + struct vxlan_sock *vs = vxlan->vn_sock; + + if (vs) + vxlan_sock_release(vn, vs); + free_percpu(dev->tstats); +} + /* Start ageing timer and join group when device is brought up */ static int vxlan_open(struct net_device *dev) { @@ -1321,6 +1332,7 @@ static void vxlan_set_multicast_list(struct net_device *dev) static const struct net_device_ops vxlan_netdev_ops = { .ndo_init = vxlan_init, + .ndo_uninit = vxlan_uninit, .ndo_open = vxlan_open, .ndo_stop = vxlan_stop, .ndo_start_xmit = vxlan_xmit, @@ -1339,12 +1351,6 @@ static struct device_type vxlan_type = { .name = "vxlan", }; -static void vxlan_free(struct net_device *dev) -{ - free_percpu(dev->tstats); - free_netdev(dev); -} - /* Initialize the device structure. */ static void vxlan_setup(struct net_device *dev) { @@ -1357,7 +1363,7 @@ static void vxlan_setup(struct net_device *dev) dev->hard_header_len = ETH_HLEN + VXLAN_HEADROOM; dev->netdev_ops = &vxlan_netdev_ops; - dev->destructor = vxlan_free; + dev->destructor = free_netdev; SET_NETDEV_DEVTYPE(dev, &vxlan_type); dev->tx_queue_len = 0; @@ -1660,14 +1666,10 @@ static int vxlan_newlink(struct net *net, struct net_device *dev, static void vxlan_dellink(struct net_device *dev, struct list_head *head) { struct vxlan_dev *vxlan = netdev_priv(dev); - struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); - struct vxlan_sock *vs = vxlan->vn_sock; hlist_del_rcu(&vxlan->hlist); list_del(&vxlan->next); unregister_netdevice_queue(dev, head); - if (vs) - vxlan_sock_release(vn, vs); } static size_t vxlan_get_size(const struct net_device *dev) |