atomic_t inet6_sock_nr;
#endif
-/* Per protocol sock slabcache */
-kmem_cache_t *tcp6_sk_cachep;
-kmem_cache_t *udp6_sk_cachep;
-kmem_cache_t *raw6_sk_cachep;
-
/* The inetsw table contains everything that inet_create needs to
* build a new socket.
*/
#endif
}
-static __inline__ kmem_cache_t *inet6_sk_slab(int protocol)
-{
- kmem_cache_t* rc = tcp6_sk_cachep;
-
- if (protocol == IPPROTO_UDP)
- rc = udp6_sk_cachep;
- else if (protocol == IPPROTO_RAW)
- rc = raw6_sk_cachep;
- return rc;
-}
-
-static __inline__ int inet6_sk_size(int protocol)
-{
- int rc = sizeof(struct tcp6_sock);
-
- if (protocol == IPPROTO_UDP)
- rc = sizeof(struct udp6_sock);
- else if (protocol == IPPROTO_RAW)
- rc = sizeof(struct raw6_sock);
- return rc;
-}
-
static __inline__ struct ipv6_pinfo *inet6_sk_generic(struct sock *sk)
{
- struct ipv6_pinfo *rc = (&((struct tcp6_sock *)sk)->inet6);
+ const int offset = sk->sk_prot->slab_obj_size - sizeof(struct ipv6_pinfo);
- if (sk->sk_protocol == IPPROTO_UDP)
- rc = (&((struct udp6_sock *)sk)->inet6);
- else if (sk->sk_protocol == IPPROTO_RAW)
- rc = (&((struct raw6_sock *)sk)->inet6);
- return rc;
+ return (struct ipv6_pinfo *)(((u8 *)sk) + offset);
}
static int inet6_create(struct socket *sock, int protocol)
struct tcp6_sock* tcp6sk;
struct list_head *p;
struct inet_protosw *answer;
-
- sk = sk_alloc(PF_INET6, GFP_KERNEL, inet6_sk_size(protocol),
- inet6_sk_slab(protocol));
- if (sk == NULL)
- goto do_oom;
+ struct proto *answer_prot;
+ unsigned char answer_flags;
+ char answer_no_check;
+ int rc;
/* Look for the requested type/protocol pair. */
answer = NULL;
answer = NULL;
}
+ rc = -ESOCKTNOSUPPORT;
if (!answer)
- goto free_and_badtype;
+ goto out_rcu_unlock;
+ rc = -EPERM;
if (answer->capability > 0 && !capable(answer->capability))
- goto free_and_badperm;
+ goto out_rcu_unlock;
+ rc = -EPROTONOSUPPORT;
if (!protocol)
- goto free_and_noproto;
+ goto out_rcu_unlock;
sock->ops = answer->ops;
+
+ answer_prot = answer->prot;
+ answer_no_check = answer->no_check;
+ answer_flags = answer->flags;
+ rcu_read_unlock();
+
+ BUG_TRAP(answer_prot->slab != NULL);
+
+ rc = -ENOBUFS;
+ sk = sk_alloc(PF_INET6, GFP_KERNEL,
+ answer_prot->slab_obj_size,
+ answer_prot->slab);
+ if (sk == NULL)
+ goto out;
+
sock_init_data(sock, sk);
sk_set_owner(sk, THIS_MODULE);
- sk->sk_prot = answer->prot;
- sk->sk_no_check = answer->no_check;
- if (INET_PROTOSW_REUSE & answer->flags)
+ rc = 0;
+ sk->sk_prot = answer_prot;
+ sk->sk_no_check = answer_no_check;
+ if (INET_PROTOSW_REUSE & answer_flags)
sk->sk_reuse = 1;
- rcu_read_unlock();
inet = inet_sk(sk);
}
sk->sk_destruct = inet6_sock_destruct;
- sk->sk_zapped = 0;
sk->sk_family = PF_INET6;
sk->sk_protocol = protocol;
sk->sk_prot->hash(sk);
}
if (sk->sk_prot->init) {
- int err = sk->sk_prot->init(sk);
- if (err != 0) {
+ rc = sk->sk_prot->init(sk);
+ if (rc) {
sk_common_release(sk);
- return err;
+ goto out;
}
}
- return 0;
-
-free_and_badtype:
- rcu_read_unlock();
- sk_free(sk);
- return -ESOCKTNOSUPPORT;
-free_and_badperm:
- rcu_read_unlock();
- sk_free(sk);
- return -EPERM;
-free_and_noproto:
+out:
+ return rc;
+out_rcu_unlock:
rcu_read_unlock();
- sk_free(sk);
- return -EPROTONOSUPPORT;
-do_oom:
- return -ENOBUFS;
+ goto out;
}
#endif
#endif
- if (sizeof(struct inet6_skb_parm) > sizeof(dummy_skb->cb))
- {
+ if (sizeof(struct inet6_skb_parm) > sizeof(dummy_skb->cb)) {
printk(KERN_CRIT "inet6_proto_init: size fault\n");
return -EINVAL;
}
- /* allocate our sock slab caches */
- tcp6_sk_cachep = kmem_cache_create("tcp6_sock",
- sizeof(struct tcp6_sock), 0,
- SLAB_HWCACHE_ALIGN, NULL, NULL);
- udp6_sk_cachep = kmem_cache_create("udp6_sock",
- sizeof(struct udp6_sock), 0,
- SLAB_HWCACHE_ALIGN, NULL, NULL);
- raw6_sk_cachep = kmem_cache_create("raw6_sock",
- sizeof(struct raw6_sock), 0,
- SLAB_HWCACHE_ALIGN, NULL, NULL);
- if (!tcp6_sk_cachep || !udp6_sk_cachep || !raw6_sk_cachep)
- printk(KERN_CRIT "%s: Can't create protocol sock SLAB "
- "caches!\n", __FUNCTION__);
+
+ err = sk_alloc_slab(&tcpv6_prot, "tcpv6_sock");
+ if (err) {
+ sk_alloc_slab_error(&tcpv6_prot);
+ goto out;
+ }
+ err = sk_alloc_slab(&udpv6_prot, "udpv6_sock");
+ if (err) {
+ sk_alloc_slab_error(&udpv6_prot);
+ goto out_tcp_free_slab;
+ }
+ err = sk_alloc_slab(&rawv6_prot, "rawv6_sock");
+ if (err) {
+ sk_alloc_slab_error(&rawv6_prot);
+ goto out_udp_free_slab;
+ }
/* Register the socket-side information for inet6_create. */
for(r = &inetsw6[0]; r < &inetsw6[SOCK_MAX]; ++r)
/* Initialise ipv6 mibs */
err = init_ipv6_mibs();
if (err)
- goto init_mib_fail;
+ goto out_raw_free_slab;
/*
* ipngwg API draft makes clear that the correct semantics
/* Init v6 transport protocols. */
udpv6_init();
tcpv6_init();
-
- return 0;
+ err = 0;
+out:
+ return err;
#ifdef CONFIG_PROC_FS
proc_if6_fail:
ipv6_sysctl_unregister();
#endif
cleanup_ipv6_mibs();
-init_mib_fail:
- return err;
+out_raw_free_slab:
+ sk_free_slab(&rawv6_prot);
+out_udp_free_slab:
+ sk_free_slab(&udpv6_prot);
+out_tcp_free_slab:
+ sk_free_slab(&tcpv6_prot);
+ goto out;
}
module_init(inet6_init);
ipv6_sysctl_unregister();
#endif
cleanup_ipv6_mibs();
- kmem_cache_destroy(tcp6_sk_cachep);
- kmem_cache_destroy(udp6_sk_cachep);
- kmem_cache_destroy(raw6_sk_cachep);
+ sk_free_slab(&rawv6_prot);
+ sk_free_slab(&udpv6_prot);
+ sk_free_slab(&tcpv6_prot);
}
module_exit(inet6_exit);