From 43062f4f0bfdaad3b1955271c8e252c9e5aade05 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 22 Apr 2003 20:53:59 -0300 Subject: [PATCH] o net: module refcounting for sk_alloc/sk_free 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 | 3 +++ net/core/sock.c | 13 +++++++++---- net/netlink/af_netlink.c | 8 +++++++- net/socket.c | 42 ++++++++++++++++++++++++++-------------- 4 files changed, 46 insertions(+), 20 deletions(-) diff --git a/include/linux/net.h b/include/linux/net.h index fc6b655dcdc3a..8b012430f49d1 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -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); diff --git a/net/core/sock.c b/net/core/sock.c index 8c85f0d79a865..29fdc583abe3a 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -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) diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index d77a9689004b6..e972bef428596 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -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"); diff --git a/net/socket.c b/net/socket.c index 0d8a2e9d5a04e..76bc02010167c 100644 --- a/net/socket.c +++ b/net/socket.c @@ -69,8 +69,6 @@ #include #include #include -#include -#include #include #include #include @@ -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 -- 2.53.0