tcp: make connect() mem charging friendly
[pandora-kernel.git] / net / ipv4 / tcp_output.c
index c51dd5b..a480116 100644 (file)
@@ -835,11 +835,13 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
                                                           &md5);
        tcp_header_size = tcp_options_size + sizeof(struct tcphdr);
 
-       if (tcp_packets_in_flight(tp) == 0) {
+       if (tcp_packets_in_flight(tp) == 0)
                tcp_ca_event(sk, CA_EVENT_TX_START);
-               skb->ooo_okay = 1;
-       } else
-               skb->ooo_okay = 0;
+
+       /* if no packet is in qdisc/device queue, then allow XPS to select
+        * another queue.
+        */
+       skb->ooo_okay = sk_wmem_alloc_get(sk) == 0;
 
        skb_push(skb, tcp_header_size);
        skb_reset_transport_header(skb);
@@ -931,6 +933,9 @@ static void tcp_queue_skb(struct sock *sk, struct sk_buff *skb)
 static void tcp_set_skb_tso_segs(const struct sock *sk, struct sk_buff *skb,
                                 unsigned int mss_now)
 {
+       /* Make sure we own this skb before messing gso_size/gso_segs */
+       WARN_ON_ONCE(skb_cloned(skb));
+
        if (skb->len <= mss_now || !sk_can_gso(sk) ||
            skb->ip_summed == CHECKSUM_NONE) {
                /* Avoid the costly divide in the normal
@@ -1012,9 +1017,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len,
        if (nsize < 0)
                nsize = 0;
 
-       if (skb_cloned(skb) &&
-           skb_is_nonlinear(skb) &&
-           pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+       if (skb_unclone(skb, GFP_ATOMIC))
                return -ENOMEM;
 
        /* Get a new skb... force flag on. */
@@ -1096,7 +1099,6 @@ static void __pskb_trim_head(struct sk_buff *skb, int len)
        eat = min_t(int, len, skb_headlen(skb));
        if (eat) {
                __skb_pull(skb, eat);
-               skb->avail_size -= eat;
                len -= eat;
                if (!len)
                        return;
@@ -1587,8 +1589,11 @@ static int tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb)
                        goto send_now;
        }
 
-       /* Ok, it looks like it is advisable to defer.  */
-       tp->tso_deferred = 1 | (jiffies << 1);
+       /* Ok, it looks like it is advisable to defer.
+        * Do not rearm the timer if already set to not break TCP ACK clocking.
+        */
+       if (!tp->tso_deferred)
+               tp->tso_deferred = 1 | (jiffies << 1);
 
        return 1;
 
@@ -2122,6 +2127,8 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
                int oldpcount = tcp_skb_pcount(skb);
 
                if (unlikely(oldpcount > 1)) {
+                       if (skb_unclone(skb, GFP_ATOMIC))
+                               return -ENOMEM;
                        tcp_init_tso_segs(sk, skb, cur_mss);
                        tcp_adjust_pcount(sk, skb, oldpcount - tcp_skb_pcount(skb));
                }
@@ -2625,13 +2632,10 @@ int tcp_connect(struct sock *sk)
 
        tcp_connect_init(sk);
 
-       buff = alloc_skb_fclone(MAX_TCP_HEADER + 15, sk->sk_allocation);
-       if (unlikely(buff == NULL))
+       buff = sk_stream_alloc_skb(sk, 0, sk->sk_allocation);
+       if (unlikely(!buff))
                return -ENOBUFS;
 
-       /* Reserve space for headers. */
-       skb_reserve(buff, MAX_TCP_HEADER);
-
        tp->snd_nxt = tp->write_seq;
        tcp_init_nondata_skb(buff, tp->write_seq++, TCPHDR_SYN);
        TCP_ECN_send_syn(sk, buff);