tcp: md5: remove spinlock usage in fast path
[pandora-kernel.git] / net / ipv4 / tcp_ipv4.c
index a9db4b1..b4e0eb4 100644 (file)
@@ -182,7 +182,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        if (IS_ERR(rt)) {
                err = PTR_ERR(rt);
                if (err == -ENETUNREACH)
-                       IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
+                       IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
                return err;
        }
 
@@ -630,7 +630,7 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
        arg.iov[0].iov_len  = sizeof(rep.th);
 
 #ifdef CONFIG_TCP_MD5SIG
-       key = sk ? tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->daddr) : NULL;
+       key = sk ? tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->saddr) : NULL;
        if (key) {
                rep.opt[0] = htonl((TCPOPT_NOP << 24) |
                                   (TCPOPT_NOP << 16) |
@@ -650,6 +650,12 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
                                      arg.iov[0].iov_len, IPPROTO_TCP, 0);
        arg.csumoffset = offsetof(struct tcphdr, check) / 2;
        arg.flags = (sk && inet_sk(sk)->transparent) ? IP_REPLY_ARG_NOSRCCHECK : 0;
+       /* When socket is gone, all binding information is lost.
+        * routing might fail in this case. No choice here, if we choose to force
+        * input interface, we will misroute in case of asymmetric route.
+        */
+       if (sk)
+               arg.bound_dev_if = sk->sk_bound_dev_if;
 
        net = dev_net(skb_dst(skb)->dev);
        arg.tos = ip_hdr(skb)->tos;
@@ -932,8 +938,7 @@ int tcp_v4_md5_do_add(struct sock *sk, __be32 addr,
                }
 
                md5sig = tp->md5sig_info;
-               if (md5sig->entries4 == 0 &&
-                   tcp_alloc_md5sig_pool(sk) == NULL) {
+               if (md5sig->entries4 == 0 && !tcp_alloc_md5sig_pool()) {
                        kfree(newkey);
                        return -ENOMEM;
                }
@@ -943,8 +948,6 @@ int tcp_v4_md5_do_add(struct sock *sk, __be32 addr,
                                        (md5sig->entries4 + 1)), GFP_ATOMIC);
                        if (!keys) {
                                kfree(newkey);
-                               if (md5sig->entries4 == 0)
-                                       tcp_free_md5sig_pool();
                                return -ENOMEM;
                        }
 
@@ -988,7 +991,6 @@ int tcp_v4_md5_do_del(struct sock *sk, __be32 addr)
                                kfree(tp->md5sig_info->keys4);
                                tp->md5sig_info->keys4 = NULL;
                                tp->md5sig_info->alloced4 = 0;
-                               tcp_free_md5sig_pool();
                        } else if (tp->md5sig_info->entries4 != i) {
                                /* Need to do some manipulation */
                                memmove(&tp->md5sig_info->keys4[i],
@@ -1016,7 +1018,6 @@ static void tcp_v4_clear_md5_list(struct sock *sk)
                for (i = 0; i < tp->md5sig_info->entries4; i++)
                        kfree(tp->md5sig_info->keys4[i].base.key);
                tp->md5sig_info->entries4 = 0;
-               tcp_free_md5sig_pool();
        }
        if (tp->md5sig_info->keys4) {
                kfree(tp->md5sig_info->keys4);
@@ -1346,7 +1347,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
                goto drop_and_free;
 
        if (!want_cookie || tmp_opt.tstamp_ok)
-               TCP_ECN_create_request(req, tcp_hdr(skb));
+               TCP_ECN_create_request(req, skb);
 
        if (want_cookie) {
                isn = cookie_v4_init_sequence(sk, skb, &req->mss);
@@ -1460,9 +1461,13 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
                inet_csk(newsk)->icsk_ext_hdr_len = inet_opt->opt.optlen;
        newinet->inet_id = newtp->write_seq ^ jiffies;
 
-       if (!dst && (dst = inet_csk_route_child_sock(sk, newsk, req)) == NULL)
-               goto put_and_exit;
-
+       if (!dst) {
+               dst = inet_csk_route_child_sock(sk, newsk, req);
+               if (!dst)
+                       goto put_and_exit;
+       } else {
+               /* syncookie case : see end of cookie_v4_check() */
+       }
        sk_setup_caps(newsk, dst);
 
        tcp_mtup_init(newsk);
@@ -1510,9 +1515,8 @@ exit:
        NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
        return NULL;
 put_and_exit:
-       tcp_clear_xmit_timers(newsk);
-       bh_unlock_sock(newsk);
-       sock_put(newsk);
+       inet_csk_prepare_forced_close(newsk);
+       tcp_done(newsk);
        goto exit;
 }
 EXPORT_SYMBOL(tcp_v4_syn_recv_sock);