[TCP]: Move __tcp_data_snd_check into tcp_output.c
[safe/jmp/linux-2.6] / net / core / sock.c
index f52c87a..a6ec3ad 100644 (file)
@@ -9,7 +9,7 @@
  *
  * Version:    $Id: sock.c,v 1.117 2002/02/01 22:01:03 davem Exp $
  *
- * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors:    Ross Biro
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *             Florian La Roche, <flla@stud.uni-sb.de>
  *             Alan Cox, <A.Cox@swansea.ac.uk>
@@ -97,7 +97,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/major.h>
 #include <linux/module.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/netdevice.h>
 #include <net/protocol.h>
 #include <linux/skbuff.h>
+#include <net/request_sock.h>
 #include <net/sock.h>
 #include <net/xfrm.h>
 #include <linux/ipsec.h>
@@ -617,10 +617,10 @@ lenout:
 
 /**
  *     sk_alloc - All socket objects are allocated here
- *     @family - protocol family
- *     @priority - for allocation (%GFP_KERNEL, %GFP_ATOMIC, etc)
- *     @prot - struct proto associated with this new sock instance
- *     @zero_it - if we should zero the newly allocated sock
+ *     @family: protocol family
+ *     @priority: for allocation (%GFP_KERNEL, %GFP_ATOMIC, etc)
+ *     @prot: struct proto associated with this new sock instance
+ *     @zero_it: if we should zero the newly allocated sock
  */
 struct sock *sk_alloc(int family, int priority, struct proto *prot, int zero_it)
 {
@@ -636,12 +636,19 @@ struct sock *sk_alloc(int family, int priority, struct proto *prot, int zero_it)
                if (zero_it) {
                        memset(sk, 0, prot->obj_size);
                        sk->sk_family = family;
-                       sk->sk_prot = prot;
+                       /*
+                        * See comment in struct sock definition to understand
+                        * why we need sk_prot_creator -acme
+                        */
+                       sk->sk_prot = sk->sk_prot_creator = prot;
                        sock_lock_init(sk);
                }
                
                if (security_sk_alloc(sk, family, priority)) {
-                       kmem_cache_free(slab, sk);
+                       if (slab != NULL)
+                               kmem_cache_free(slab, sk);
+                       else
+                               kfree(sk);
                        sk = NULL;
                } else
                        __module_get(prot->owner);
@@ -652,7 +659,7 @@ struct sock *sk_alloc(int family, int priority, struct proto *prot, int zero_it)
 void sk_free(struct sock *sk)
 {
        struct sk_filter *filter;
-       struct module *owner = sk->sk_prot->owner;
+       struct module *owner = sk->sk_prot_creator->owner;
 
        if (sk->sk_destruct)
                sk->sk_destruct(sk);
@@ -670,8 +677,8 @@ void sk_free(struct sock *sk)
                       __FUNCTION__, atomic_read(&sk->sk_omem_alloc));
 
        security_sk_free(sk);
-       if (sk->sk_prot->slab != NULL)
-               kmem_cache_free(sk->sk_prot->slab, sk);
+       if (sk->sk_prot_creator->slab != NULL)
+               kmem_cache_free(sk->sk_prot_creator->slab, sk);
        else
                kfree(sk);
        module_put(owner);
@@ -968,8 +975,8 @@ static void __release_sock(struct sock *sk)
 
 /**
  * sk_wait_data - wait for data to arrive at sk_receive_queue
- * sk - sock to wait on
- * timeo - for how long
+ * @sk:    sock to wait on
+ * @timeo: for how long
  *
  * Now socket state including sk->sk_err is changed only under lock,
  * hence we may omit checks after joining wait queue.
@@ -1357,6 +1364,7 @@ static LIST_HEAD(proto_list);
 
 int proto_register(struct proto *prot, int alloc_slab)
 {
+       char *request_sock_slab_name;
        int rc = -ENOBUFS;
 
        if (alloc_slab) {
@@ -1368,6 +1376,25 @@ int proto_register(struct proto *prot, int alloc_slab)
                               prot->name);
                        goto out;
                }
+
+               if (prot->rsk_prot != NULL) {
+                       static const char mask[] = "request_sock_%s";
+
+                       request_sock_slab_name = kmalloc(strlen(prot->name) + sizeof(mask) - 1, GFP_KERNEL);
+                       if (request_sock_slab_name == NULL)
+                               goto out_free_sock_slab;
+
+                       sprintf(request_sock_slab_name, mask, prot->name);
+                       prot->rsk_prot->slab = kmem_cache_create(request_sock_slab_name,
+                                                                prot->rsk_prot->obj_size, 0,
+                                                                SLAB_HWCACHE_ALIGN, NULL, NULL);
+
+                       if (prot->rsk_prot->slab == NULL) {
+                               printk(KERN_CRIT "%s: Can't create request sock SLAB cache!\n",
+                                      prot->name);
+                               goto out_free_request_sock_slab_name;
+                       }
+               }
        }
 
        write_lock(&proto_list_lock);
@@ -1376,6 +1403,12 @@ int proto_register(struct proto *prot, int alloc_slab)
        rc = 0;
 out:
        return rc;
+out_free_request_sock_slab_name:
+       kfree(request_sock_slab_name);
+out_free_sock_slab:
+       kmem_cache_destroy(prot->slab);
+       prot->slab = NULL;
+       goto out;
 }
 
 EXPORT_SYMBOL(proto_register);
@@ -1389,6 +1422,14 @@ void proto_unregister(struct proto *prot)
                prot->slab = NULL;
        }
 
+       if (prot->rsk_prot != NULL && prot->rsk_prot->slab != NULL) {
+               const char *name = kmem_cache_name(prot->rsk_prot->slab);
+
+               kmem_cache_destroy(prot->rsk_prot->slab);
+               kfree(name);
+               prot->rsk_prot->slab = NULL;
+       }
+
        list_del(&prot->node);
        write_unlock(&proto_list_lock);
 }