X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fipv6%2Faf_inet6.c;h=2f3136c3eb873ee1af3d4e90f13a9018e2f1ce59;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=33e39d2201c1a58795fdea3fe721821da2ad1803;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 33e39d220..2f3136c3e 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -90,11 +90,6 @@ int sysctl_ipv6_bindv6only; 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. */ @@ -110,37 +105,11 @@ static void inet6_sock_destruct(struct sock *sk) #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) @@ -151,11 +120,10 @@ 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; @@ -179,22 +147,40 @@ static int inet6_create(struct socket *sock, int protocol) 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); @@ -205,7 +191,6 @@ static int inet6_create(struct socket *sock, int protocol) } sk->sk_destruct = inet6_sock_destruct; - sk->sk_zapped = 0; sk->sk_family = PF_INET6; sk->sk_protocol = protocol; @@ -248,28 +233,17 @@ static int inet6_create(struct socket *sock, int protocol) sk->sk_prot->hash(sk); } if (sk->sk_prot->init) { - int err = sk->sk_prot->init(sk); - if (err != 0) { - inet_sock_release(sk); - return err; + rc = sk->sk_prot->init(sk); + if (rc) { + sk_common_release(sk); + 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; } @@ -510,10 +484,10 @@ struct proto_ops inet6_stream_ops = { .ioctl = inet6_ioctl, /* must change */ .listen = inet_listen, /* ok */ .shutdown = inet_shutdown, /* ok */ - .setsockopt = inet_setsockopt, /* ok */ - .getsockopt = inet_getsockopt, /* ok */ + .setsockopt = sock_common_setsockopt, /* ok */ + .getsockopt = sock_common_getsockopt, /* ok */ .sendmsg = inet_sendmsg, /* ok */ - .recvmsg = inet_recvmsg, /* ok */ + .recvmsg = sock_common_recvmsg, /* ok */ .mmap = sock_no_mmap, .sendpage = tcp_sendpage }; @@ -531,10 +505,10 @@ struct proto_ops inet6_dgram_ops = { .ioctl = inet6_ioctl, /* must change */ .listen = sock_no_listen, /* ok */ .shutdown = inet_shutdown, /* ok */ - .setsockopt = inet_setsockopt, /* ok */ - .getsockopt = inet_getsockopt, /* ok */ + .setsockopt = sock_common_setsockopt, /* ok */ + .getsockopt = sock_common_getsockopt, /* ok */ .sendmsg = inet_sendmsg, /* ok */ - .recvmsg = inet_recvmsg, /* ok */ + .recvmsg = sock_common_recvmsg, /* ok */ .mmap = sock_no_mmap, .sendpage = sock_no_sendpage, }; @@ -560,8 +534,6 @@ static struct inet_protosw rawv6_protosw = { .flags = INET_PROTOSW_REUSE, }; -#define INETSW6_ARRAY_LEN (sizeof(inetsw6_array) / sizeof(struct inet_protosw)) - void inet6_register_protosw(struct inet_protosw *p) { @@ -711,24 +683,26 @@ static int __init inet6_init(void) #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, 0, 0); - udp6_sk_cachep = kmem_cache_create("udp6_sock", - sizeof(struct udp6_sock), 0, - SLAB_HWCACHE_ALIGN, 0, 0); - raw6_sk_cachep = kmem_cache_create("raw6_sock", - sizeof(struct raw6_sock), 0, - SLAB_HWCACHE_ALIGN, 0, 0); - 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) @@ -747,7 +721,7 @@ static int __init inet6_init(void) /* 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 @@ -800,8 +774,9 @@ static int __init inet6_init(void) /* Init v6 transport protocols. */ udpv6_init(); tcpv6_init(); - - return 0; + err = 0; +out: + return err; #ifdef CONFIG_PROC_FS proc_if6_fail: @@ -826,8 +801,13 @@ icmp_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); @@ -856,9 +836,9 @@ static void __exit inet6_exit(void) 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);