struct sk_buff *skb,
                                              const struct tcphdr *th);
 struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
-                          struct request_sock *req, bool fastopen);
+                          struct request_sock *req, bool fastopen,
+                          bool *lost_race);
 int tcp_child_process(struct sock *parent, struct sock *child,
                      struct sk_buff *skb);
 void tcp_enter_loss(struct sock *sk);
 
        tp->rx_opt.saw_tstamp = 0;
        req = tp->fastopen_rsk;
        if (req) {
+               bool req_stolen;
+
                WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV &&
                    sk->sk_state != TCP_FIN_WAIT1);
 
-               if (!tcp_check_req(sk, skb, req, true))
+               if (!tcp_check_req(sk, skb, req, true, &req_stolen))
                        goto discard;
        }
 
 
 
        if (sk->sk_state == TCP_NEW_SYN_RECV) {
                struct request_sock *req = inet_reqsk(sk);
+               bool req_stolen = false;
                struct sock *nsk;
 
                sk = req->rsk_listener;
                        th = (const struct tcphdr *)skb->data;
                        iph = ip_hdr(skb);
                        tcp_v4_fill_cb(skb, iph, th);
-                       nsk = tcp_check_req(sk, skb, req, false);
+                       nsk = tcp_check_req(sk, skb, req, false, &req_stolen);
                }
                if (!nsk) {
                        reqsk_put(req);
+                       if (req_stolen) {
+                               /* Another cpu got exclusive access to req
+                                * and created a full blown socket.
+                                * Try to feed this packet to this socket
+                                * instead of discarding it.
+                                */
+                               tcp_v4_restore_cb(skb);
+                               sock_put(sk);
+                               goto lookup;
+                       }
                        goto discard_and_relse;
                }
                if (nsk == sk) {
 
 
 struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
                           struct request_sock *req,
-                          bool fastopen)
+                          bool fastopen, bool *req_stolen)
 {
        struct tcp_options_received tmp_opt;
        struct sock *child;
 
        sock_rps_save_rxhash(child, skb);
        tcp_synack_rtt_meas(child, req);
+       *req_stolen = !own_req;
        return inet_csk_complete_hashdance(sk, child, req, own_req);
 
 listen_overflow:
 
 
        if (sk->sk_state == TCP_NEW_SYN_RECV) {
                struct request_sock *req = inet_reqsk(sk);
+               bool req_stolen = false;
                struct sock *nsk;
 
                sk = req->rsk_listener;
                        th = (const struct tcphdr *)skb->data;
                        hdr = ipv6_hdr(skb);
                        tcp_v6_fill_cb(skb, hdr, th);
-                       nsk = tcp_check_req(sk, skb, req, false);
+                       nsk = tcp_check_req(sk, skb, req, false, &req_stolen);
                }
                if (!nsk) {
                        reqsk_put(req);
+                       if (req_stolen) {
+                               /* Another cpu got exclusive access to req
+                                * and created a full blown socket.
+                                * Try to feed this packet to this socket
+                                * instead of discarding it.
+                                */
+                               tcp_v6_restore_cb(skb);
+                               sock_put(sk);
+                               goto lookup;
+                       }
                        goto discard_and_relse;
                }
                if (nsk == sk) {