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).
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);
*/
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);
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);
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)
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)
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;
}
remove_proc_entry("net/netlink", NULL);
}
-module_init(netlink_proto_init);
+subsys_initcall(netlink_proto_init);
module_exit(netlink_proto_exit);
MODULE_LICENSE("GPL");
#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>
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;
sock->ops->release(sock);
sock->ops = NULL;
- module_put(net_families[family]->owner);
+ net_family_put(family);
}
if (sock->fasync_list)
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)
* 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