[TUN]: Introduce the tun_net structure and init/exit net ops.
authorPavel Emelyanov <xemul@openvz.org>
Wed, 16 Apr 2008 07:40:46 +0000 (00:40 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 16 Apr 2008 07:40:46 +0000 (00:40 -0700)
This is the first step in making tuntap devices work in net
namespaces. The structure mentioned is pointed by generic
net pointer with tun_net_id id, and tun driver fills one on
its load. It will contain only the tun devices list.

So declare this structure and introduce net init and exit hooks.

Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/tun.c

index 5b5d875..f359d60 100644 (file)
@@ -63,6 +63,7 @@
 #include <linux/if_tun.h>
 #include <linux/crc32.h>
 #include <net/net_namespace.h>
+#include <net/netns/generic.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -106,6 +107,11 @@ struct tun_struct {
 
 /* Network device part of the driver */
 
+static unsigned int tun_net_id;
+struct tun_net {
+       struct list_head dev_list;
+};
+
 static LIST_HEAD(tun_dev_list);
 static const struct ethtool_ops tun_ethtool_ops;
 
@@ -909,6 +915,37 @@ static const struct ethtool_ops tun_ethtool_ops = {
        .set_rx_csum    = tun_set_rx_csum
 };
 
+static int tun_init_net(struct net *net)
+{
+       struct tun_net *tn;
+
+       tn = kmalloc(sizeof(*tn), GFP_KERNEL);
+       if (tn == NULL)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(&tn->dev_list);
+
+       if (net_assign_generic(net, tun_net_id, tn)) {
+               kfree(tn);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+static void tun_exit_net(struct net *net)
+{
+       struct tun_net *tn;
+
+       tn = net_generic(net, tun_net_id);
+       kfree(tn);
+}
+
+static struct pernet_operations tun_net_ops = {
+       .init = tun_init_net,
+       .exit = tun_exit_net,
+};
+
 static int __init tun_init(void)
 {
        int ret = 0;
@@ -916,9 +953,22 @@ static int __init tun_init(void)
        printk(KERN_INFO "tun: %s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
        printk(KERN_INFO "tun: %s\n", DRV_COPYRIGHT);
 
+       ret = register_pernet_gen_device(&tun_net_id, &tun_net_ops);
+       if (ret) {
+               printk(KERN_ERR "tun: Can't register pernet ops\n");
+               goto err_pernet;
+       }
+
        ret = misc_register(&tun_miscdev);
-       if (ret)
+       if (ret) {
                printk(KERN_ERR "tun: Can't register misc device %d\n", TUN_MINOR);
+               goto err_misc;
+       }
+       return 0;
+
+err_misc:
+       unregister_pernet_gen_device(tun_net_id, &tun_net_ops);
+err_pernet:
        return ret;
 }
 
@@ -935,6 +985,7 @@ static void tun_cleanup(void)
        }
        rtnl_unlock();
 
+       unregister_pernet_gen_device(tun_net_id, &tun_net_ops);
 }
 
 module_init(tun_init);