ip6_tun: Add infrastructure for doing encapsulation
[cascardo/linux.git] / net / ipv4 / tcp.c
index cb4d1ca..5c7ed14 100644 (file)
@@ -1084,6 +1084,7 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
        struct sockcm_cookie sockc;
        int flags, err, copied = 0;
        int mss_now = 0, size_goal, copied_syn = 0;
+       bool process_backlog = false;
        bool sg;
        long timeo;
 
@@ -1136,11 +1137,12 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
        /* This should be in poll */
        sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk);
 
-       mss_now = tcp_send_mss(sk, &size_goal, flags);
-
        /* Ok commence sending. */
        copied = 0;
 
+restart:
+       mss_now = tcp_send_mss(sk, &size_goal, flags);
+
        err = -EPIPE;
        if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN))
                goto out_err;
@@ -1166,6 +1168,10 @@ new_segment:
                        if (!sk_stream_memory_free(sk))
                                goto wait_for_sndbuf;
 
+                       if (process_backlog && sk_flush_backlog(sk)) {
+                               process_backlog = false;
+                               goto restart;
+                       }
                        skb = sk_stream_alloc_skb(sk,
                                                  select_size(sk, sg),
                                                  sk->sk_allocation,
@@ -1173,6 +1179,7 @@ new_segment:
                        if (!skb)
                                goto wait_for_memory;
 
+                       process_backlog = true;
                        /*
                         * Check whether we can use HW checksum.
                         */
@@ -1449,12 +1456,8 @@ static void tcp_prequeue_process(struct sock *sk)
 
        NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPPREQUEUED);
 
-       /* RX process wants to run with disabled BHs, though it is not
-        * necessary */
-       local_bh_disable();
        while ((skb = __skb_dequeue(&tp->ucopy.prequeue)) != NULL)
                sk_backlog_rcv(sk, skb);
-       local_bh_enable();
 
        /* Clear memory counter. */
        tp->ucopy.memory = 0;
@@ -3095,7 +3098,7 @@ void tcp_done(struct sock *sk)
        struct request_sock *req = tcp_sk(sk)->fastopen_rsk;
 
        if (sk->sk_state == TCP_SYN_SENT || sk->sk_state == TCP_SYN_RECV)
-               __TCP_INC_STATS(sock_net(sk), TCP_MIB_ATTEMPTFAILS);
+               TCP_INC_STATS(sock_net(sk), TCP_MIB_ATTEMPTFAILS);
 
        tcp_set_state(sk, TCP_CLOSE);
        tcp_clear_xmit_timers(sk);