diff options
Diffstat (limited to 'quicktun.c')
-rw-r--r-- | quicktun.c | 49 |
1 files changed, 13 insertions, 36 deletions
@@ -3,8 +3,8 @@ #include <linux/if_arp.h> #include <linux/ip.h> #include <linux/ipv6.h> +#include <linux/list.h> #include <linux/netdevice.h> -#include <linux/rculist.h> #include <linux/udp.h> #include <net/dst.h> #include <net/genetlink.h> @@ -28,6 +28,8 @@ static LIST_HEAD(quicktun_list); struct quicktun_struct { + struct list_head list; + struct net_device *dev; unsigned long flags; @@ -38,13 +40,6 @@ struct quicktun_struct { }; -struct quicktun_list_entry { - struct list_head list; - struct rcu_head rcu; - struct quicktun_struct *quicktun; -}; - - static netdev_tx_t quicktun_net_xmit(struct sk_buff *skb, struct net_device *dev) { struct quicktun_struct *tun = netdev_priv(dev); @@ -276,7 +271,6 @@ static int quicktun_cmd_create_device(struct sk_buff *skb, struct genl_info *inf struct quicktun_struct *tun; struct net *net = genl_info_net(info); struct net_device *dev; - struct quicktun_list_entry *entry; char *name = "qt%d"; int err; @@ -298,20 +292,16 @@ static int quicktun_cmd_create_device(struct sk_buff *skb, struct genl_info *inf if (info->attrs[QUICKTUN_A_IFNAME]) name = nla_data(info->attrs[QUICKTUN_A_IFNAME]); - entry = kmalloc(sizeof(struct quicktun_struct), GFP_KERNEL); dev = alloc_netdev(sizeof(struct quicktun_struct), name, quicktun_setup); - if (!entry || !dev) { - err = -ENOMEM; - goto err_free; - } + if (!dev) + return -ENOMEM; dev_net_set(dev, net); tun = netdev_priv(dev); tun->dev = dev; tun->flags = flags; - entry->quicktun = tun; quicktun_net_init(dev); @@ -337,7 +327,7 @@ static int quicktun_cmd_create_device(struct sk_buff *skb, struct genl_info *inf err = quicktun_socket_init(dev); if (err < 0) - goto err_free; + goto err_free_dev; rtnl_lock(); @@ -351,7 +341,7 @@ static int quicktun_cmd_create_device(struct sk_buff *skb, struct genl_info *inf if (err < 0) goto err_free_sk; - list_add_tail_rcu(&entry->list, &quicktun_list); + list_add_tail(&tun->list, &quicktun_list); rtnl_unlock(); @@ -361,30 +351,17 @@ static int quicktun_cmd_create_device(struct sk_buff *skb, struct genl_info *inf rtnl_unlock(); sock_release(tun->sock); - err_free: - if (dev) free_netdev(dev); - if (entry) kfree(entry); + err_free_dev: + free_netdev(dev); return err; } -static void quicktun_free_list_entry(struct rcu_head *rcu) { - struct quicktun_list_entry *entry = container_of(rcu, struct quicktun_list_entry, rcu); - kfree(entry); -} static void __quicktun_delete_device(struct net_device *dev) { struct quicktun_struct *tun = netdev_priv(dev); struct socket *sock = tun->sock; - struct quicktun_list_entry *entry = NULL; - - list_for_each_entry(entry, &quicktun_list, list) { - if (entry->quicktun->dev == dev) { - break; - } - } - list_del_rcu(&entry->list); - call_rcu(&entry->rcu, quicktun_free_list_entry); + list_del(&tun->list); unregister_netdevice(dev); sock_release(sock); @@ -424,7 +401,7 @@ static int quicktun_cmd_delete_device(struct sk_buff *skb, struct genl_info *inf return 0; -err_unlock: + err_unlock: rtnl_unlock(); return err; @@ -475,14 +452,14 @@ static int __init quicktun_init(void) static void quicktun_exit(void) { - struct quicktun_list_entry *entry, *next; + struct quicktun_struct *entry, *next; genl_unregister_family(&quicktun_nl_family); rtnl_lock(); list_for_each_entry_safe(entry, next, &quicktun_list, list) { - __quicktun_delete_device(entry->quicktun->dev); + __quicktun_delete_device(entry->dev); } rtnl_unlock(); |