Merge with ../linux-2.6-smp
[deliverable/linux.git] / net / ipv4 / tcp.c
index a037bafcba3c09234e7bfcfbf59f15acb71a8f95..674bbd8cfd36d03c98dafa1770fc5daccb2b13f0 100644 (file)
@@ -271,7 +271,6 @@ int sysctl_tcp_fin_timeout = TCP_FIN_TIMEOUT;
 
 DEFINE_SNMP_STAT(struct tcp_mib, tcp_statistics);
 
-kmem_cache_t *tcp_openreq_cachep;
 kmem_cache_t *tcp_bucket_cachep;
 kmem_cache_t *tcp_timewait_cachep;
 
@@ -317,7 +316,7 @@ EXPORT_SYMBOL(tcp_enter_memory_pressure);
 static __inline__ unsigned int tcp_listen_poll(struct sock *sk,
                                               poll_table *wait)
 {
-       return tcp_sk(sk)->accept_queue ? (POLLIN | POLLRDNORM) : 0;
+       return !reqsk_queue_empty(&tcp_sk(sk)->accept_queue) ? (POLLIN | POLLRDNORM) : 0;
 }
 
 /*
@@ -463,28 +462,15 @@ int tcp_listen_start(struct sock *sk)
 {
        struct inet_sock *inet = inet_sk(sk);
        struct tcp_sock *tp = tcp_sk(sk);
-       struct tcp_listen_opt *lopt;
+       int rc = reqsk_queue_alloc(&tp->accept_queue, TCP_SYNQ_HSIZE);
+
+       if (rc != 0)
+               return rc;
 
        sk->sk_max_ack_backlog = 0;
        sk->sk_ack_backlog = 0;
-       tp->accept_queue = tp->accept_queue_tail = NULL;
-       rwlock_init(&tp->syn_wait_lock);
        tcp_delack_init(tp);
 
-       lopt = kmalloc(sizeof(struct tcp_listen_opt), GFP_KERNEL);
-       if (!lopt)
-               return -ENOMEM;
-
-       memset(lopt, 0, sizeof(struct tcp_listen_opt));
-       for (lopt->max_qlen_log = 6; ; lopt->max_qlen_log++)
-               if ((1 << lopt->max_qlen_log) >= sysctl_max_syn_backlog)
-                       break;
-       get_random_bytes(&lopt->hash_rnd, 4);
-
-       write_lock_bh(&tp->syn_wait_lock);
-       tp->listen_opt = lopt;
-       write_unlock_bh(&tp->syn_wait_lock);
-
        /* There is race window here: we announce ourselves listening,
         * but this transition is still not validated by get_port().
         * It is OK, because this socket enters to hash table only
@@ -501,10 +487,7 @@ int tcp_listen_start(struct sock *sk)
        }
 
        sk->sk_state = TCP_CLOSE;
-       write_lock_bh(&tp->syn_wait_lock);
-       tp->listen_opt = NULL;
-       write_unlock_bh(&tp->syn_wait_lock);
-       kfree(lopt);
+       reqsk_queue_destroy(&tp->accept_queue);
        return -EADDRINUSE;
 }
 
@@ -516,25 +499,23 @@ int tcp_listen_start(struct sock *sk)
 static void tcp_listen_stop (struct sock *sk)
 {
        struct tcp_sock *tp = tcp_sk(sk);
-       struct tcp_listen_opt *lopt = tp->listen_opt;
-       struct open_request *acc_req = tp->accept_queue;
-       struct open_request *req;
+       struct listen_sock *lopt;
+       struct request_sock *acc_req;
+       struct request_sock *req;
        int i;
 
        tcp_delete_keepalive_timer(sk);
 
        /* make all the listen_opt local to us */
-       write_lock_bh(&tp->syn_wait_lock);
-       tp->listen_opt = NULL;
-       write_unlock_bh(&tp->syn_wait_lock);
-       tp->accept_queue = tp->accept_queue_tail = NULL;
+       lopt = reqsk_queue_yank_listen_sk(&tp->accept_queue);
+       acc_req = reqsk_queue_yank_acceptq(&tp->accept_queue);
 
        if (lopt->qlen) {
                for (i = 0; i < TCP_SYNQ_HSIZE; i++) {
                        while ((req = lopt->syn_table[i]) != NULL) {
                                lopt->syn_table[i] = req->dl_next;
                                lopt->qlen--;
-                               tcp_openreq_free(req);
+                               reqsk_free(req);
 
                /* Following specs, it would be better either to send FIN
                 * (and enter FIN-WAIT-1, it is normal close)
@@ -574,7 +555,7 @@ static void tcp_listen_stop (struct sock *sk)
                sock_put(child);
 
                sk_acceptq_removed(sk);
-               tcp_openreq_fastfree(req);
+               __reqsk_free(req);
        }
        BUG_TRAP(!sk->sk_ack_backlog);
 }
@@ -1345,7 +1326,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 
                cleanup_rbuf(sk, copied);
 
-               if (tp->ucopy.task == user_recv) {
+               if (!sysctl_tcp_low_latency && tp->ucopy.task == user_recv) {
                        /* Install new reader */
                        if (!user_recv && !(flags & (MSG_TRUNC | MSG_PEEK))) {
                                user_recv = current;
@@ -1868,11 +1849,11 @@ static int wait_for_connect(struct sock *sk, long timeo)
                prepare_to_wait_exclusive(sk->sk_sleep, &wait,
                                          TASK_INTERRUPTIBLE);
                release_sock(sk);
-               if (!tp->accept_queue)
+               if (reqsk_queue_empty(&tp->accept_queue))
                        timeo = schedule_timeout(timeo);
                lock_sock(sk);
                err = 0;
-               if (tp->accept_queue)
+               if (!reqsk_queue_empty(&tp->accept_queue))
                        break;
                err = -EINVAL;
                if (sk->sk_state != TCP_LISTEN)
@@ -1895,7 +1876,6 @@ static int wait_for_connect(struct sock *sk, long timeo)
 struct sock *tcp_accept(struct sock *sk, int flags, int *err)
 {
        struct tcp_sock *tp = tcp_sk(sk);
-       struct open_request *req;
        struct sock *newsk;
        int error;
 
@@ -1906,37 +1886,31 @@ struct sock *tcp_accept(struct sock *sk, int flags, int *err)
         */
        error = -EINVAL;
        if (sk->sk_state != TCP_LISTEN)
-               goto out;
+               goto out_err;
 
        /* Find already established connection */
-       if (!tp->accept_queue) {
+       if (reqsk_queue_empty(&tp->accept_queue)) {
                long timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
 
                /* If this is a non blocking socket don't sleep */
                error = -EAGAIN;
                if (!timeo)
-                       goto out;
+                       goto out_err;
 
                error = wait_for_connect(sk, timeo);
                if (error)
-                       goto out;
+                       goto out_err;
        }
 
-       req = tp->accept_queue;
-       if ((tp->accept_queue = req->dl_next) == NULL)
-               tp->accept_queue_tail = NULL;
-
-       newsk = req->sk;
-       sk_acceptq_removed(sk);
-       tcp_openreq_fastfree(req);
+       newsk = reqsk_queue_get_child(&tp->accept_queue, sk);
        BUG_TRAP(newsk->sk_state != TCP_SYN_RECV);
-       release_sock(sk);
-       return newsk;
-
 out:
        release_sock(sk);
+       return newsk;
+out_err:
+       newsk = NULL;
        *err = error;
-       return NULL;
+       goto out;
 }
 
 /*
@@ -2271,13 +2245,6 @@ void __init tcp_init(void)
                __skb_cb_too_small_for_tcp(sizeof(struct tcp_skb_cb),
                                           sizeof(skb->cb));
 
-       tcp_openreq_cachep = kmem_cache_create("tcp_open_request",
-                                                  sizeof(struct open_request),
-                                              0, SLAB_HWCACHE_ALIGN,
-                                              NULL, NULL);
-       if (!tcp_openreq_cachep)
-               panic("tcp_init: Cannot alloc open_request cache.");
-
        tcp_bucket_cachep = kmem_cache_create("tcp_bind_bucket",
                                              sizeof(struct tcp_bind_bucket),
                                              0, SLAB_HWCACHE_ALIGN,
@@ -2338,7 +2305,7 @@ void __init tcp_init(void)
                        (tcp_bhash_size * sizeof(struct tcp_bind_hashbucket));
                        order++)
                ;
-       if (order > 4) {
+       if (order >= 4) {
                sysctl_local_port_range[0] = 32768;
                sysctl_local_port_range[1] = 61000;
                sysctl_tcp_max_tw_buckets = 180000;
@@ -2374,7 +2341,6 @@ EXPORT_SYMBOL(tcp_destroy_sock);
 EXPORT_SYMBOL(tcp_disconnect);
 EXPORT_SYMBOL(tcp_getsockopt);
 EXPORT_SYMBOL(tcp_ioctl);
-EXPORT_SYMBOL(tcp_openreq_cachep);
 EXPORT_SYMBOL(tcp_poll);
 EXPORT_SYMBOL(tcp_read_sock);
 EXPORT_SYMBOL(tcp_recvmsg);
This page took 0.037843 seconds and 5 git commands to generate.