]> git.hungrycats.org Git - linux/commitdiff
o net: module refcounting for sk_alloc/sk_free
authorArnaldo Carvalho de Melo <acme@conectiva.com.br>
Tue, 22 Apr 2003 23:53:59 +0000 (20:53 -0300)
committerArnaldo Carvalho de Melo <acme@conectiva.com.br>
Tue, 22 Apr 2003 23:53:59 +0000 (20:53 -0300)
I had to move the rtnetlink_init and init_netlink calls to af_netlink init time, so that
the sk_alloc called down the rtnetlink_init callchain is done after the PF_NETLINK
net_proto_family is sock_registered, and because of that the af_netlink init function
call had to be moved to earlier by means of subsys_initcall (DaveM's suggestion).

include/linux/net.h
net/core/sock.c
net/netlink/af_netlink.c
net/socket.c

index fc6b655dcdc3af6981dc9d55a4dfb7bf108a2215..8b012430f49d1bae1cd0d8b02c6597f4141806b8 100644 (file)
@@ -140,6 +140,9 @@ struct net_proto_family {
        struct module   *owner;
 };
 
+extern int          net_family_get(int family);
+extern void         net_family_put(int family);
+
 struct iovec;
 
 extern int          sock_wake_async(struct socket *sk, int how, int band);
index 8c85f0d79a86521a28afa58c294acd1682ebcf9c..29fdc583abe3aaec4051e147396b768bee6d2166 100644 (file)
@@ -589,8 +589,10 @@ static kmem_cache_t *sk_cachep;
  */
 struct sock *sk_alloc(int family, int priority, int zero_it, kmem_cache_t *slab)
 {
-       struct sock *sk;
-       
+       struct sock *sk = NULL;
+
+       if (!net_family_get(family))
+               goto out;
        if (!slab)
                slab = sk_cachep;
        sk = kmem_cache_alloc(slab, priority);
@@ -602,14 +604,16 @@ struct sock *sk_alloc(int family, int priority, int zero_it, kmem_cache_t *slab)
                        sock_lock_init(sk);
                }
                sk->slab = slab;
-       }
-
+       } else
+               net_family_put(family);
+out:
        return sk;
 }
 
 void sk_free(struct sock *sk)
 {
        struct sk_filter *filter;
+       const int family = sk->family;
 
        if (sk->destruct)
                sk->destruct(sk);
@@ -624,6 +628,7 @@ void sk_free(struct sock *sk)
                printk(KERN_DEBUG "sk_free: optmem leakage (%d bytes) detected.\n", atomic_read(&sk->omem_alloc));
 
        kmem_cache_free(sk->slab, sk);
+       net_family_put(family);
 }
 
 void __init sk_init(void)
index d77a9689004b6cbe261bfb23387fd521e1a3ea0f..e972bef4285960a98f803b7aea11443a7a9742dd 100644 (file)
@@ -1052,6 +1052,7 @@ struct proto_ops netlink_ops = {
 struct net_proto_family netlink_family_ops = {
        .family = PF_NETLINK,
        .create = netlink_create,
+       .owner  = THIS_MODULE,  /* for consistency 8) */
 };
 
 static int __init netlink_proto_init(void)
@@ -1065,6 +1066,11 @@ static int __init netlink_proto_init(void)
        sock_register(&netlink_family_ops);
 #ifdef CONFIG_PROC_FS
        create_proc_read_entry("net/netlink", 0, 0, netlink_read_proc, NULL);
+#endif
+       /* The netlink device handler may be needed early. */ 
+       rtnetlink_init();
+#ifdef CONFIG_NETLINK_DEV
+       init_netlink();
 #endif
        return 0;
 }
@@ -1075,7 +1081,7 @@ static void __exit netlink_proto_exit(void)
        remove_proc_entry("net/netlink", NULL);
 }
 
-module_init(netlink_proto_init);
+subsys_initcall(netlink_proto_init);
 module_exit(netlink_proto_exit);
 
 MODULE_LICENSE("GPL");
index 0d8a2e9d5a04eb4e593da368a70c3c25b9dd9c00..76bc02010167cdde47af4eb4cbc4f037ec288bc5 100644 (file)
@@ -69,8 +69,6 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/wanrouter.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
 #include <linux/if_bridge.h>
 #include <linux/init.h>
 #include <linux/poll.h>
@@ -143,6 +141,31 @@ static struct file_operations socket_file_ops = {
 
 static struct net_proto_family *net_families[NPROTO];
 
+static __inline__ void net_family_bug(int family)
+{
+       printk(KERN_ERR "%d is not yet sock_registered!\n", family);
+       BUG();
+}
+
+int net_family_get(int family)
+{
+       int rc = 1;
+
+       if (likely(net_families[family] != NULL))
+               rc = try_module_get(net_families[family]->owner);
+       else
+               net_family_bug(family);
+       return rc;
+}
+
+void net_family_put(int family)
+{
+       if (likely(net_families[family] != NULL))
+               module_put(net_families[family]->owner);
+       else
+               net_family_bug(family);
+}
+
 #if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
 static atomic_t net_family_lockct = ATOMIC_INIT(0);
 static spinlock_t net_family_lock = SPIN_LOCK_UNLOCKED;
@@ -511,7 +534,7 @@ void sock_release(struct socket *sock)
 
                sock->ops->release(sock);
                sock->ops = NULL;
-               module_put(net_families[family]->owner);
+               net_family_put(family);
        }
 
        if (sock->fasync_list)
@@ -1064,7 +1087,7 @@ int sock_create(int family, int type, int protocol, struct socket **res)
        sock->type  = type;
 
        i = -EBUSY;
-       if (!try_module_get(net_families[family]->owner))
+       if (!net_family_get(family))
                goto out_release;
 
        if ((i = net_families[family]->create(sock, protocol)) < 0) 
@@ -1953,17 +1976,6 @@ void __init sock_init(void)
         *  do_initcalls is run.  
         */
 
-
-       /*
-        * The netlink device handler may be needed early.
-        */
-
-#ifdef CONFIG_NET
-       rtnetlink_init();
-#endif
-#ifdef CONFIG_NETLINK_DEV
-       init_netlink();
-#endif
 #ifdef CONFIG_NETFILTER
        netfilter_init();
 #endif