]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - net/ipv4/tcp_ipv4.c
Merge branch 'master' into csb1725
[mv-sheeva.git] / net / ipv4 / tcp_ipv4.c
index 020766292bb01009201ec11e60bb0e214854414c..d978bb2f748b34d99efb0162e4e083a460275630 100644 (file)
@@ -415,6 +415,9 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
                    !icsk->icsk_backoff)
                        break;
 
+               if (sock_owned_by_user(sk))
+                       break;
+
                icsk->icsk_backoff--;
                inet_csk(sk)->icsk_rto = __tcp_set_rto(tp) <<
                                         icsk->icsk_backoff;
@@ -429,11 +432,6 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
                if (remaining) {
                        inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
                                                  remaining, TCP_RTO_MAX);
-               } else if (sock_owned_by_user(sk)) {
-                       /* RTO revert clocked out retransmission,
-                        * but socket is locked. Will defer. */
-                       inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
-                                                 HZ/20, TCP_RTO_MAX);
                } else {
                        /* RTO revert clocked out retransmission.
                         * Will retransmit now */
@@ -1422,7 +1420,7 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
 
        newsk = tcp_create_openreq_child(sk, req, skb);
        if (!newsk)
-               goto exit;
+               goto exit_nonewsk;
 
        newsk->sk_gso_type = SKB_GSO_TCPV4;
        sk_setup_caps(newsk, dst);
@@ -1469,16 +1467,20 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
        }
 #endif
 
+       if (__inet_inherit_port(sk, newsk) < 0) {
+               sock_put(newsk);
+               goto exit;
+       }
        __inet_hash_nolisten(newsk, NULL);
-       __inet_inherit_port(sk, newsk);
 
        return newsk;
 
 exit_overflow:
        NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
+exit_nonewsk:
+       dst_release(dst);
 exit:
        NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
-       dst_release(dst);
        return NULL;
 }
 EXPORT_SYMBOL(tcp_v4_syn_recv_sock);
@@ -2028,7 +2030,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
 get_req:
                        req = icsk->icsk_accept_queue.listen_opt->syn_table[st->sbucket];
                }
-               sk        = sk_next(st->syn_wait_sk);
+               sk        = sk_nulls_next(st->syn_wait_sk);
                st->state = TCP_SEQ_STATE_LISTENING;
                read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
        } else {
@@ -2037,11 +2039,13 @@ get_req:
                if (reqsk_queue_len(&icsk->icsk_accept_queue))
                        goto start_req;
                read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
-               sk = sk_next(sk);
+               sk = sk_nulls_next(sk);
        }
 get_sk:
        sk_nulls_for_each_from(sk, node) {
-               if (sk->sk_family == st->family && net_eq(sock_net(sk), net)) {
+               if (!net_eq(sock_net(sk), net))
+                       continue;
+               if (sk->sk_family == st->family) {
                        cur = sk;
                        goto out;
                }
@@ -2571,7 +2575,6 @@ struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *skb)
 
        return tcp_gro_receive(head, skb);
 }
-EXPORT_SYMBOL(tcp4_gro_receive);
 
 int tcp4_gro_complete(struct sk_buff *skb)
 {
@@ -2584,7 +2587,6 @@ int tcp4_gro_complete(struct sk_buff *skb)
 
        return tcp_gro_complete(skb);
 }
-EXPORT_SYMBOL(tcp4_gro_complete);
 
 struct proto tcp_prot = {
        .name                   = "TCP",