diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2013-10-14 19:21:11 +0200 |
---|---|---|
committer | Matthias Schiffer <mschiffer@universe-factory.net> | 2013-10-14 19:21:11 +0200 |
commit | 807fde8a03408dd659112cce7bd75813366fea9b (patch) | |
tree | 8a9450c15d2ca83e7932c632377f236fa16cd073 | |
parent | 6e93844647f2af858cf1ee4d6351f6f78dc1e5b7 (diff) | |
download | modfastd-807fde8a03408dd659112cce7bd75813366fea9b.tar modfastd-807fde8a03408dd659112cce7bd75813366fea9b.zip |
Free netdev in rcu callback
-rw-r--r-- | fastd.c | 41 | ||||
-rw-r--r-- | fastd.h | 9 |
2 files changed, 27 insertions, 23 deletions
@@ -89,6 +89,7 @@ struct fastd_struct { struct list_head sockets; struct work_struct destroy_work; + struct rcu_head rcu; }; struct fastd_socket { @@ -204,27 +205,9 @@ static const struct ethtool_ops fastd_ethtool_ops = { }; -static void fastd_netdev_free(struct net_device *dev) -{ - struct fastd_struct *fastd = netdev_priv(dev); - struct fastd_socket *socket, *next; - - list_for_each_entry_safe(socket, next, &fastd->sockets, list) { - list_del(&socket->list); - sock_release(socket->sock); - kfree(socket); - } - - put_net(fastd->net); - free_netdev(dev); - - module_put(THIS_MODULE); -} - static void fastd_netdev_setup(struct net_device *dev) { dev->ethtool_ops = &fastd_ethtool_ops; - dev->destructor = fastd_netdev_free; } static inline u16 fastd_header_len(u16 mode) @@ -262,6 +245,24 @@ static void fastd_netdev_init(struct net_device *dev) dev->hard_header_len = fastd_header_len(fastd->mode); } +static void fastd_netdev_free(struct rcu_head *rcu) +{ + struct fastd_struct *fastd = container_of(rcu, struct fastd_struct, + rcu); + struct fastd_socket *socket, *next; + + list_for_each_entry_safe(socket, next, &fastd->sockets, list) { + list_del(&socket->list); + sk_release_kernel(socket->sock->sk); + kfree(socket); + } + + put_net(fastd->net); + free_netdev(fastd->dev); + + module_put(THIS_MODULE); +} + static void fastd_destroy_work(struct work_struct *work) { struct fastd_struct *fastd = container_of(work, struct fastd_struct, @@ -273,6 +274,8 @@ static void fastd_destroy_work(struct work_struct *work) unregister_netdevice(fastd->dev); rtnl_unlock(); + + call_rcu(&fastd->rcu, fastd_netdev_free); } static int fastd_cmd_create(struct sk_buff *skb, struct genl_info *info) @@ -413,7 +416,7 @@ err_unlock_rcu: rcu_read_unlock(); err_release_sock: - sock_release(socket->sock); + sk_release_kernel(socket->sock->sk); err_free_socket: kfree(socket); @@ -40,15 +40,16 @@ #define __LINUX_FASTD_H enum { - FASTD_MODE_ETH = 1, - FASTD_MODE_IP + FASTD_MODE_UNSPEC, + FASTD_MODE_ETH, + FASTD_MODE_IP, }; enum { FASTD_CMD_UNSPEC, FASTD_CMD_CREATE, FASTD_CMD_BIND, - __FASTD_CMD_MAX + __FASTD_CMD_MAX, }; enum { @@ -58,7 +59,7 @@ enum { FASTD_A_MTU, FASTD_A_LOCALADDR, FASTD_A_REMOTEADDR, - __FASTD_A_MAX + __FASTD_A_MAX, }; |