From 807fde8a03408dd659112cce7bd75813366fea9b Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 14 Oct 2013 19:21:11 +0200 Subject: Free netdev in rcu callback --- fastd.c | 41 ++++++++++++++++++++++------------------- fastd.h | 9 +++++---- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/fastd.c b/fastd.c index c9afc67..00dd41e 100644 --- a/fastd.c +++ b/fastd.c @@ -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); diff --git a/fastd.h b/fastd.h index 55878cc..3017c18 100644 --- a/fastd.h +++ b/fastd.h @@ -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, }; -- cgit v1.2.3