tcp: md5: remove spinlock usage in fast path
[pandora-kernel.git] / net / ipv6 / tcp_ipv6.c
index ccab3c8..655cc60 100644 (file)
@@ -592,7 +592,7 @@ static int tcp_v6_md5_do_add(struct sock *sk, const struct in6_addr *peer,
                        sk_nocaps_add(sk, NETIF_F_GSO_MASK);
                }
                if (tp->md5sig_info->entries6 == 0 &&
-                       tcp_alloc_md5sig_pool(sk) == NULL) {
+                   !tcp_alloc_md5sig_pool()) {
                        kfree(newkey);
                        return -ENOMEM;
                }
@@ -602,8 +602,6 @@ static int tcp_v6_md5_do_add(struct sock *sk, const struct in6_addr *peer,
 
                        if (!keys) {
                                kfree(newkey);
-                               if (tp->md5sig_info->entries6 == 0)
-                                       tcp_free_md5sig_pool();
                                return -ENOMEM;
                        }
 
@@ -649,7 +647,6 @@ static int tcp_v6_md5_do_del(struct sock *sk, const struct in6_addr *peer)
                                kfree(tp->md5sig_info->keys6);
                                tp->md5sig_info->keys6 = NULL;
                                tp->md5sig_info->alloced6 = 0;
-                               tcp_free_md5sig_pool();
                        } else {
                                /* shrink the database */
                                if (tp->md5sig_info->entries6 != i)
@@ -673,7 +670,6 @@ static void tcp_v6_clear_md5_list (struct sock *sk)
                for (i = 0; i < tp->md5sig_info->entries6; i++)
                        kfree(tp->md5sig_info->keys6[i].base.key);
                tp->md5sig_info->entries6 = 0;
-               tcp_free_md5sig_pool();
        }
 
        kfree(tp->md5sig_info->keys6);
@@ -684,7 +680,6 @@ static void tcp_v6_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();
        }
 
        kfree(tp->md5sig_info->keys4);
@@ -1254,7 +1249,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
        ipv6_addr_copy(&treq->rmt_addr, &ipv6_hdr(skb)->saddr);
        ipv6_addr_copy(&treq->loc_addr, &ipv6_hdr(skb)->daddr);
        if (!want_cookie || tmp_opt.tstamp_ok)
-               TCP_ECN_create_request(req, tcp_hdr(skb));
+               TCP_ECN_create_request(req, skb);
 
        treq->iif = sk->sk_bound_dev_if;
 
@@ -1524,7 +1519,8 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
 #endif
 
        if (__inet_inherit_port(sk, newsk) < 0) {
-               sock_put(newsk);
+               inet_csk_prepare_forced_close(newsk);
+               tcp_done(newsk);
                goto out;
        }
        __inet6_hash(newsk, NULL);
@@ -2195,6 +2191,17 @@ void tcp6_proc_exit(struct net *net)
 }
 #endif
 
+static void tcp_v6_clear_sk(struct sock *sk, int size)
+{
+       struct inet_sock *inet = inet_sk(sk);
+
+       /* we do not want to clear pinet6 field, because of RCU lookups */
+       sk_prot_clear_nulls(sk, offsetof(struct inet_sock, pinet6));
+
+       size -= offsetof(struct inet_sock, pinet6) + sizeof(inet->pinet6);
+       memset(&inet->pinet6 + 1, 0, size);
+}
+
 struct proto tcpv6_prot = {
        .name                   = "TCPv6",
        .owner                  = THIS_MODULE,
@@ -2234,6 +2241,7 @@ struct proto tcpv6_prot = {
        .compat_setsockopt      = compat_tcp_setsockopt,
        .compat_getsockopt      = compat_tcp_getsockopt,
 #endif
+       .clear_sk               = tcp_v6_clear_sk,
 };
 
 static const struct inet6_protocol tcpv6_protocol = {