aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/tun.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2009-01-20 05:56:20 -0500
committerDavid S. Miller <davem@davemloft.net>2009-01-21 19:00:43 -0500
commit74a3e5a71c9b54c63bff978e9cafbcef67600f0b (patch)
treeb6c3c043a40e62e5ba0e922c90545ee2a986616f /drivers/net/tun.c
parentf5882c30508c1e3c4fbbdaa9ca08d0922c5fb071 (diff)
tun: Remove unnecessary tun_get_by_name
Currently the tun driver keeps a private list of tun devices for what appears to be a small gain in performance when reconnecting a file descriptor to an existing tun or tap device. So simplify the code by removing it. Signed-off-by: Eric W. Biederman <ebiederm@aristanetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/tun.c')
-rw-r--r--drivers/net/tun.c74
1 files changed, 19 insertions, 55 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index d7b81e4fdd56..17923a508535 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -88,7 +88,6 @@ struct tap_filter {
88}; 88};
89 89
90struct tun_struct { 90struct tun_struct {
91 struct list_head list;
92 unsigned int flags; 91 unsigned int flags;
93 int attached; 92 int attached;
94 uid_t owner; 93 uid_t owner;
@@ -213,11 +212,6 @@ static int check_filter(struct tap_filter *filter, const struct sk_buff *skb)
213 212
214/* Network device part of the driver */ 213/* Network device part of the driver */
215 214
216static int tun_net_id;
217struct tun_net {
218 struct list_head dev_list;
219};
220
221static const struct ethtool_ops tun_ethtool_ops; 215static const struct ethtool_ops tun_ethtool_ops;
222 216
223/* Net device open. */ 217/* Net device open. */
@@ -697,30 +691,22 @@ static void tun_setup(struct net_device *dev)
697 dev->features |= NETIF_F_NETNS_LOCAL; 691 dev->features |= NETIF_F_NETNS_LOCAL;
698} 692}
699 693
700static struct tun_struct *tun_get_by_name(struct tun_net *tn, const char *name)
701{
702 struct tun_struct *tun;
703
704 ASSERT_RTNL();
705 list_for_each_entry(tun, &tn->dev_list, list) {
706 if (!strncmp(tun->dev->name, name, IFNAMSIZ))
707 return tun;
708 }
709
710 return NULL;
711}
712
713static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) 694static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
714{ 695{
715 struct tun_net *tn;
716 struct tun_struct *tun; 696 struct tun_struct *tun;
717 struct net_device *dev; 697 struct net_device *dev;
718 const struct cred *cred = current_cred(); 698 const struct cred *cred = current_cred();
719 int err; 699 int err;
720 700
721 tn = net_generic(net, tun_net_id); 701 dev = __dev_get_by_name(net, ifr->ifr_name);
722 tun = tun_get_by_name(tn, ifr->ifr_name); 702 if (dev) {
723 if (tun) { 703 if ((ifr->ifr_flags & IFF_TUN) && dev->netdev_ops == &tun_netdev_ops)
704 tun = netdev_priv(dev);
705 else if ((ifr->ifr_flags & IFF_TAP) && dev->netdev_ops == &tap_netdev_ops)
706 tun = netdev_priv(dev);
707 else
708 return -EINVAL;
709
724 if (tun->attached) 710 if (tun->attached)
725 return -EBUSY; 711 return -EBUSY;
726 712
@@ -733,8 +719,6 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
733 return -EPERM; 719 return -EPERM;
734 } 720 }
735 } 721 }
736 else if (__dev_get_by_name(net, ifr->ifr_name))
737 return -EINVAL;
738 else { 722 else {
739 char *name; 723 char *name;
740 unsigned long flags = 0; 724 unsigned long flags = 0;
@@ -782,8 +766,6 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
782 err = register_netdevice(tun->dev); 766 err = register_netdevice(tun->dev);
783 if (err < 0) 767 if (err < 0)
784 goto err_free_dev; 768 goto err_free_dev;
785
786 list_add(&tun->list, &tn->dev_list);
787 } 769 }
788 770
789 DBG(KERN_INFO "%s: tun_set_iff\n", tun->dev->name); 771 DBG(KERN_INFO "%s: tun_set_iff\n", tun->dev->name);
@@ -1095,10 +1077,8 @@ static int tun_chr_close(struct inode *inode, struct file *file)
1095 /* Drop read queue */ 1077 /* Drop read queue */
1096 skb_queue_purge(&tun->readq); 1078 skb_queue_purge(&tun->readq);
1097 1079
1098 if (!(tun->flags & TUN_PERSIST)) { 1080 if (!(tun->flags & TUN_PERSIST))
1099 list_del(&tun->list);
1100 unregister_netdevice(tun->dev); 1081 unregister_netdevice(tun->dev);
1101 }
1102 1082
1103 rtnl_unlock(); 1083 rtnl_unlock();
1104 1084
@@ -1212,37 +1192,21 @@ static const struct ethtool_ops tun_ethtool_ops = {
1212 1192
1213static int tun_init_net(struct net *net) 1193static int tun_init_net(struct net *net)
1214{ 1194{
1215 struct tun_net *tn;
1216
1217 tn = kmalloc(sizeof(*tn), GFP_KERNEL);
1218 if (tn == NULL)
1219 return -ENOMEM;
1220
1221 INIT_LIST_HEAD(&tn->dev_list);
1222
1223 if (net_assign_generic(net, tun_net_id, tn)) {
1224 kfree(tn);
1225 return -ENOMEM;
1226 }
1227
1228 return 0; 1195 return 0;
1229} 1196}
1230 1197
1231static void tun_exit_net(struct net *net) 1198static void tun_exit_net(struct net *net)
1232{ 1199{
1233 struct tun_net *tn; 1200 struct net_device *dev, *next;
1234 struct tun_struct *tun, *nxt;
1235
1236 tn = net_generic(net, tun_net_id);
1237 1201
1238 rtnl_lock(); 1202 rtnl_lock();
1239 list_for_each_entry_safe(tun, nxt, &tn->dev_list, list) { 1203 for_each_netdev_safe(net, dev, next) {
1240 DBG(KERN_INFO "%s cleaned up\n", tun->dev->name); 1204 if (dev->ethtool_ops != &tun_ethtool_ops)
1241 unregister_netdevice(tun->dev); 1205 continue;
1206 DBG(KERN_INFO "%s cleaned up\n", dev->name);
1207 unregister_netdevice(dev);
1242 } 1208 }
1243 rtnl_unlock(); 1209 rtnl_unlock();
1244
1245 kfree(tn);
1246} 1210}
1247 1211
1248static struct pernet_operations tun_net_ops = { 1212static struct pernet_operations tun_net_ops = {
@@ -1257,7 +1221,7 @@ static int __init tun_init(void)
1257 printk(KERN_INFO "tun: %s, %s\n", DRV_DESCRIPTION, DRV_VERSION); 1221 printk(KERN_INFO "tun: %s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
1258 printk(KERN_INFO "tun: %s\n", DRV_COPYRIGHT); 1222 printk(KERN_INFO "tun: %s\n", DRV_COPYRIGHT);
1259 1223
1260 ret = register_pernet_gen_device(&tun_net_id, &tun_net_ops); 1224 ret = register_pernet_device(&tun_net_ops);
1261 if (ret) { 1225 if (ret) {
1262 printk(KERN_ERR "tun: Can't register pernet ops\n"); 1226 printk(KERN_ERR "tun: Can't register pernet ops\n");
1263 goto err_pernet; 1227 goto err_pernet;
@@ -1271,7 +1235,7 @@ static int __init tun_init(void)
1271 return 0; 1235 return 0;
1272 1236
1273err_misc: 1237err_misc:
1274 unregister_pernet_gen_device(tun_net_id, &tun_net_ops); 1238 unregister_pernet_device(&tun_net_ops);
1275err_pernet: 1239err_pernet:
1276 return ret; 1240 return ret;
1277} 1241}
@@ -1279,7 +1243,7 @@ err_pernet:
1279static void tun_cleanup(void) 1243static void tun_cleanup(void)
1280{ 1244{
1281 misc_deregister(&tun_miscdev); 1245 misc_deregister(&tun_miscdev);
1282 unregister_pernet_gen_device(tun_net_id, &tun_net_ops); 1246 unregister_pernet_device(&tun_net_ops);
1283} 1247}
1284 1248
1285module_init(tun_init); 1249module_init(tun_init);