nommu: clamp zone_batchsize() to 0 under NOMMU conditions
[safe/jmp/linux-2.6] / net / ipv4 / tcp_output.c
index 61445b5..59aec60 100644 (file)
@@ -441,10 +441,7 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp,
                        *ptr++ = htonl(sp[this_sack].end_seq);
                }
 
-               if (tp->rx_opt.dsack) {
-                       tp->rx_opt.dsack = 0;
-                       tp->rx_opt.eff_sacks = tp->rx_opt.num_sacks;
-               }
+               tp->rx_opt.dsack = 0;
        }
 }
 
@@ -550,6 +547,7 @@ static unsigned tcp_established_options(struct sock *sk, struct sk_buff *skb,
        struct tcp_skb_cb *tcb = skb ? TCP_SKB_CB(skb) : NULL;
        struct tcp_sock *tp = tcp_sk(sk);
        unsigned size = 0;
+       unsigned int eff_sacks;
 
 #ifdef CONFIG_TCP_MD5SIG
        *md5 = tp->af_specific->md5_lookup(sk, sk);
@@ -568,10 +566,11 @@ static unsigned tcp_established_options(struct sock *sk, struct sk_buff *skb,
                size += TCPOLEN_TSTAMP_ALIGNED;
        }
 
-       if (unlikely(tp->rx_opt.eff_sacks)) {
+       eff_sacks = tp->rx_opt.num_sacks + tp->rx_opt.dsack;
+       if (unlikely(eff_sacks)) {
                const unsigned remaining = MAX_TCP_OPTION_SPACE - size;
                opts->num_sack_blocks =
-                       min_t(unsigned, tp->rx_opt.eff_sacks,
+                       min_t(unsigned, eff_sacks,
                              (remaining - TCPOLEN_SACK_BASE_ALIGNED) /
                              TCPOLEN_SACK_PERBLOCK);
                size += TCPOLEN_SACK_BASE_ALIGNED +
@@ -755,6 +754,36 @@ static void tcp_adjust_fackets_out(struct sock *sk, struct sk_buff *skb,
                tp->fackets_out -= decr;
 }
 
+/* Pcount in the middle of the write queue got changed, we need to do various
+ * tweaks to fix counters
+ */
+static void tcp_adjust_pcount(struct sock *sk, struct sk_buff *skb, int decr)
+{
+       struct tcp_sock *tp = tcp_sk(sk);
+
+       tp->packets_out -= decr;
+
+       if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)
+               tp->sacked_out -= decr;
+       if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS)
+               tp->retrans_out -= decr;
+       if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST)
+               tp->lost_out -= decr;
+
+       /* Reno case is special. Sigh... */
+       if (tcp_is_reno(tp) && decr > 0)
+               tp->sacked_out -= min_t(u32, tp->sacked_out, decr);
+
+       tcp_adjust_fackets_out(sk, skb, decr);
+
+       if (tp->lost_skb_hint &&
+           before(TCP_SKB_CB(skb)->seq, TCP_SKB_CB(tp->lost_skb_hint)->seq) &&
+           (tcp_is_fack(tp) || (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)))
+               tp->lost_cnt_hint -= decr;
+
+       tcp_verify_left_out(tp);
+}
+
 /* Function to create two new TCP segments.  Shrinks the given segment
  * to the specified size and appends a new segment with the rest of the
  * packet to the list.  This won't be called frequently, I hope.
@@ -767,7 +796,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len,
        struct sk_buff *buff;
        int nsize, old_factor;
        int nlen;
-       u16 flags;
+       u8 flags;
 
        BUG_ON(len > skb->len);
 
@@ -837,28 +866,8 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len,
                int diff = old_factor - tcp_skb_pcount(skb) -
                        tcp_skb_pcount(buff);
 
-               tp->packets_out -= diff;
-
-               if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)
-                       tp->sacked_out -= diff;
-               if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS)
-                       tp->retrans_out -= diff;
-
-               if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST)
-                       tp->lost_out -= diff;
-
-               /* Adjust Reno SACK estimate. */
-               if (tcp_is_reno(tp) && diff > 0) {
-                       tcp_dec_pcount_approx_int(&tp->sacked_out, diff);
-                       tcp_verify_left_out(tp);
-               }
-               tcp_adjust_fackets_out(sk, skb, diff);
-
-               if (tp->lost_skb_hint &&
-                   before(TCP_SKB_CB(skb)->seq,
-                          TCP_SKB_CB(tp->lost_skb_hint)->seq) &&
-                   (tcp_is_fack(tp) || TCP_SKB_CB(skb)->sacked))
-                       tp->lost_cnt_hint -= diff;
+               if (diff)
+                       tcp_adjust_pcount(sk, skb, diff);
        }
 
        /* Link BUFF into the send queue. */
@@ -922,7 +931,7 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
         * factor and mss.
         */
        if (tcp_skb_pcount(skb) > 1)
-               tcp_set_skb_tso_segs(sk, skb, tcp_current_mss(sk, 1));
+               tcp_set_skb_tso_segs(sk, skb, tcp_current_mss(sk));
 
        return 0;
 }
@@ -983,15 +992,6 @@ void tcp_mtup_init(struct sock *sk)
        icsk->icsk_mtup.probe_size = 0;
 }
 
-/* Bound MSS / TSO packet size with the half of the window */
-static int tcp_bound_to_half_wnd(struct tcp_sock *tp, int pktsize)
-{
-       if (tp->max_window && pktsize > (tp->max_window >> 1))
-               return max(tp->max_window >> 1, 68U - tp->tcp_header_len);
-       else
-               return pktsize;
-}
-
 /* This function synchronize snd mss to current pmtu/exthdr set.
 
    tp->rx_opt.user_mss is mss set by user by TCP_MAXSEG. It does NOT counts
@@ -1038,22 +1038,17 @@ unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu)
 /* Compute the current effective MSS, taking SACKs and IP options,
  * and even PMTU discovery events into account.
  */
-unsigned int tcp_current_mss(struct sock *sk, int large_allowed)
+unsigned int tcp_current_mss(struct sock *sk)
 {
        struct tcp_sock *tp = tcp_sk(sk);
        struct dst_entry *dst = __sk_dst_get(sk);
        u32 mss_now;
-       u16 xmit_size_goal;
-       int doing_tso = 0;
        unsigned header_len;
        struct tcp_out_options opts;
        struct tcp_md5sig_key *md5;
 
        mss_now = tp->mss_cache;
 
-       if (large_allowed && sk_can_gso(sk))
-               doing_tso = 1;
-
        if (dst) {
                u32 mtu = dst_mtu(dst);
                if (mtu != inet_csk(sk)->icsk_pmtu_cookie)
@@ -1071,19 +1066,6 @@ unsigned int tcp_current_mss(struct sock *sk, int large_allowed)
                mss_now -= delta;
        }
 
-       xmit_size_goal = mss_now;
-
-       if (doing_tso) {
-               xmit_size_goal = ((sk->sk_gso_max_size - 1) -
-                                 inet_csk(sk)->icsk_af_ops->net_header_len -
-                                 inet_csk(sk)->icsk_ext_hdr_len -
-                                 tp->tcp_header_len);
-
-               xmit_size_goal = tcp_bound_to_half_wnd(tp, xmit_size_goal);
-               xmit_size_goal -= (xmit_size_goal % mss_now);
-       }
-       tp->xmit_size_goal = xmit_size_goal;
-
        return mss_now;
 }
 
@@ -1265,7 +1247,7 @@ int tcp_may_send_now(struct sock *sk)
        struct sk_buff *skb = tcp_send_head(sk);
 
        return (skb &&
-               tcp_snd_test(sk, skb, tcp_current_mss(sk, 1),
+               tcp_snd_test(sk, skb, tcp_current_mss(sk),
                             (tcp_skb_is_last(sk, skb) ?
                              tp->nonagle : TCP_NAGLE_PUSH)));
 }
@@ -1282,7 +1264,7 @@ static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len,
 {
        struct sk_buff *buff;
        int nlen = skb->len - len;
-       u16 flags;
+       u8 flags;
 
        /* All of a TSO frame must be composed of paged data.  */
        if (skb->len != skb->data_len)
@@ -1418,11 +1400,11 @@ static int tcp_mtu_probe(struct sock *sk)
            icsk->icsk_mtup.probe_size ||
            inet_csk(sk)->icsk_ca_state != TCP_CA_Open ||
            tp->snd_cwnd < 11 ||
-           tp->rx_opt.eff_sacks)
+           tp->rx_opt.num_sacks || tp->rx_opt.dsack)
                return -1;
 
        /* Very simple search strategy: just double the MSS. */
-       mss_now = tcp_current_mss(sk, 0);
+       mss_now = tcp_current_mss(sk);
        probe_size = 2 * tp->mss_cache;
        size_needed = probe_size + (tp->reordering + 1) * tp->mss_cache;
        if (probe_size > tcp_mtu_to_mss(sk, icsk->icsk_mtup.search_high)) {
@@ -1796,22 +1778,14 @@ static void tcp_collapse_retrans(struct sock *sk, struct sk_buff *skb)
         * packet counting does not break.
         */
        TCP_SKB_CB(skb)->sacked |= TCP_SKB_CB(next_skb)->sacked & TCPCB_EVER_RETRANS;
-       if (TCP_SKB_CB(next_skb)->sacked & TCPCB_SACKED_RETRANS)
-               tp->retrans_out -= tcp_skb_pcount(next_skb);
-       if (TCP_SKB_CB(next_skb)->sacked & TCPCB_LOST)
-               tp->lost_out -= tcp_skb_pcount(next_skb);
-       /* Reno case is special. Sigh... */
-       if (tcp_is_reno(tp) && tp->sacked_out)
-               tcp_dec_pcount_approx(&tp->sacked_out, next_skb);
-
-       tcp_adjust_fackets_out(sk, next_skb, tcp_skb_pcount(next_skb));
-       tp->packets_out -= tcp_skb_pcount(next_skb);
 
        /* changed transmit queue under us so clear hints */
        tcp_clear_retrans_hints_partial(tp);
        if (next_skb == tp->retransmit_skb_hint)
                tp->retransmit_skb_hint = skb;
 
+       tcp_adjust_pcount(sk, next_skb, tcp_skb_pcount(next_skb));
+
        sk_wmem_free_skb(sk, next_skb);
 }
 
@@ -1904,7 +1878,7 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
        if (inet_csk(sk)->icsk_af_ops->rebuild_header(sk))
                return -EHOSTUNREACH; /* Routing failure or similar. */
 
-       cur_mss = tcp_current_mss(sk, 0);
+       cur_mss = tcp_current_mss(sk);
 
        /* If receiver has shrunk his window, and skb is out of
         * new window, do not retransmit it. The exception is the
@@ -1919,7 +1893,12 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
                if (tcp_fragment(sk, skb, cur_mss, cur_mss))
                        return -ENOMEM; /* We'll try again later. */
        } else {
-               tcp_init_tso_segs(sk, skb, cur_mss);
+               int oldpcount = tcp_skb_pcount(skb);
+
+               if (unlikely(oldpcount > 1)) {
+                       tcp_init_tso_segs(sk, skb, cur_mss);
+                       tcp_adjust_pcount(sk, skb, oldpcount - tcp_skb_pcount(skb));
+               }
        }
 
        tcp_retrans_try_collapse(sk, skb, cur_mss);
@@ -2112,7 +2091,7 @@ void tcp_send_fin(struct sock *sk)
         * unsent frames.  But be careful about outgoing SACKS
         * and IP options.
         */
-       mss_now = tcp_current_mss(sk, 1);
+       mss_now = tcp_current_mss(sk);
 
        if (tcp_send_head(sk) != NULL) {
                TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_FIN;
@@ -2337,7 +2316,7 @@ static void tcp_connect_init(struct sock *sk)
        sk->sk_err = 0;
        sock_reset_flag(sk, SOCK_DONE);
        tp->snd_wnd = 0;
-       tcp_init_wl(tp, tp->write_seq, 0);
+       tcp_init_wl(tp, 0);
        tp->snd_una = tp->write_seq;
        tp->snd_sml = tp->write_seq;
        tp->snd_up = tp->write_seq;
@@ -2524,7 +2503,7 @@ int tcp_write_wakeup(struct sock *sk)
        if ((skb = tcp_send_head(sk)) != NULL &&
            before(TCP_SKB_CB(skb)->seq, tcp_wnd_end(tp))) {
                int err;
-               unsigned int mss = tcp_current_mss(sk, 0);
+               unsigned int mss = tcp_current_mss(sk);
                unsigned int seg_size = tcp_wnd_end(tp) - TCP_SKB_CB(skb)->seq;
 
                if (before(tp->pushed_seq, TCP_SKB_CB(skb)->end_seq))