const struct request_sock *req);
 
 struct request_sock *inet6_csk_search_req(const struct sock *sk,
-                                         struct request_sock ***prevp,
                                          const __be16 rport,
                                          const struct in6_addr *raddr,
                                          const struct in6_addr *laddr,
 
 struct sock *inet_csk_accept(struct sock *sk, int flags, int *err);
 
 struct request_sock *inet_csk_search_req(const struct sock *sk,
-                                        struct request_sock ***prevp,
                                         const __be16 rport,
                                         const __be32 raddr,
                                         const __be32 laddr);
 }
 
 static inline void inet_csk_reqsk_queue_unlink(struct sock *sk,
-                                              struct request_sock *req,
-                                              struct request_sock **prev)
+                                              struct request_sock *req)
 {
-       reqsk_queue_unlink(&inet_csk(sk)->icsk_accept_queue, req, prev);
+       reqsk_queue_unlink(&inet_csk(sk)->icsk_accept_queue, req);
 }
 
 static inline void inet_csk_reqsk_queue_drop(struct sock *sk,
-                                            struct request_sock *req,
-                                            struct request_sock **prev)
+                                            struct request_sock *req)
 {
-       inet_csk_reqsk_queue_unlink(sk, req, prev);
+       inet_csk_reqsk_queue_unlink(sk, req);
        inet_csk_reqsk_queue_removed(sk, req);
        reqsk_free(req);
 }
 
 struct request_sock {
        struct sock_common              __req_common;
 #define rsk_refcnt                     __req_common.skc_refcnt
+#define rsk_hash                       __req_common.skc_hash
 
        struct request_sock             *dl_next;
        struct sock                     *rsk_listener;
 }
 
 static inline void reqsk_queue_unlink(struct request_sock_queue *queue,
-                                     struct request_sock *req,
-                                     struct request_sock **prev_req)
+                                     struct request_sock *req)
 {
+       struct listen_sock *lopt = queue->listen_opt;
+       struct request_sock **prev;
+
        write_lock(&queue->syn_wait_lock);
-       *prev_req = req->dl_next;
+       prev = &lopt->syn_table[req->rsk_hash];
+       while (*prev != req)
+               prev = &(*prev)->dl_next;
+       *prev = req->dl_next;
        write_unlock(&queue->syn_wait_lock);
 }
 
        req->num_retrans = 0;
        req->num_timeout = 0;
        req->sk = NULL;
-       req->dl_next = lopt->syn_table[hash];
 
        /* before letting lookups find us, make sure all req fields
         * are committed to memory and refcnt initialized.
        smp_wmb();
        atomic_set(&req->rsk_refcnt, 1);
 
+       req->rsk_hash = hash;
        write_lock(&queue->syn_wait_lock);
+       req->dl_next = lopt->syn_table[hash];
        lopt->syn_table[hash] = req;
        write_unlock(&queue->syn_wait_lock);
 }
 
                                              struct sk_buff *skb,
                                              const struct tcphdr *th);
 struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
-                          struct request_sock *req, struct request_sock **prev,
-                          bool fastopen);
+                          struct request_sock *req, bool fastopen);
 int tcp_child_process(struct sock *parent, struct sock *child,
                      struct sk_buff *skb);
 void tcp_enter_loss(struct sock *sk);
 
                                       struct request_sock *req,
                                       struct dst_entry *dst);
 struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
-                           struct request_sock *req,
-                           struct request_sock **prev);
+                           struct request_sock *req);
 
 int dccp_child_process(struct sock *parent, struct sock *child,
                       struct sk_buff *skb);
 
        }
 
        switch (sk->sk_state) {
-               struct request_sock *req , **prev;
+               struct request_sock *req;
        case DCCP_LISTEN:
                if (sock_owned_by_user(sk))
                        goto out;
-               req = inet_csk_search_req(sk, &prev, dh->dccph_dport,
+               req = inet_csk_search_req(sk, dh->dccph_dport,
                                          iph->daddr, iph->saddr);
                if (!req)
                        goto out;
                 * created socket, and POSIX does not want network
                 * errors returned from accept().
                 */
-               inet_csk_reqsk_queue_drop(sk, req, prev);
+               inet_csk_reqsk_queue_drop(sk, req);
                goto out;
 
        case DCCP_REQUESTING:
        const struct dccp_hdr *dh = dccp_hdr(skb);
        const struct iphdr *iph = ip_hdr(skb);
        struct sock *nsk;
-       struct request_sock **prev;
        /* Find possible connection requests. */
-       struct request_sock *req = inet_csk_search_req(sk, &prev,
-                                                      dh->dccph_sport,
+       struct request_sock *req = inet_csk_search_req(sk, dh->dccph_sport,
                                                       iph->saddr, iph->daddr);
-       if (req != NULL)
-               return dccp_check_req(sk, skb, req, prev);
+       if (req)
+               return dccp_check_req(sk, skb, req);
 
        nsk = inet_lookup_established(sock_net(sk), &dccp_hashinfo,
                                      iph->saddr, dh->dccph_sport,
 
 
        /* Might be for an request_sock */
        switch (sk->sk_state) {
-               struct request_sock *req, **prev;
+               struct request_sock *req;
        case DCCP_LISTEN:
                if (sock_owned_by_user(sk))
                        goto out;
 
-               req = inet6_csk_search_req(sk, &prev, dh->dccph_dport,
+               req = inet6_csk_search_req(sk, dh->dccph_dport,
                                           &hdr->daddr, &hdr->saddr,
                                           inet6_iif(skb));
                if (req == NULL)
                        goto out;
                }
 
-               inet_csk_reqsk_queue_drop(sk, req, prev);
+               inet_csk_reqsk_queue_drop(sk, req);
                goto out;
 
        case DCCP_REQUESTING:
 {
        const struct dccp_hdr *dh = dccp_hdr(skb);
        const struct ipv6hdr *iph = ipv6_hdr(skb);
+       struct request_sock *req;
        struct sock *nsk;
-       struct request_sock **prev;
-       /* Find possible connection requests. */
-       struct request_sock *req = inet6_csk_search_req(sk, &prev,
-                                                       dh->dccph_sport,
-                                                       &iph->saddr,
-                                                       &iph->daddr,
-                                                       inet6_iif(skb));
+
+       req = inet6_csk_search_req(sk, dh->dccph_sport, &iph->saddr,
+                                  &iph->daddr, inet6_iif(skb));
        if (req != NULL)
-               return dccp_check_req(sk, skb, req, prev);
+               return dccp_check_req(sk, skb, req);
 
        nsk = __inet6_lookup_established(sock_net(sk), &dccp_hashinfo,
                                         &iph->saddr, dh->dccph_sport,
 
  * as an request_sock.
  */
 struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
-                           struct request_sock *req,
-                           struct request_sock **prev)
+                           struct request_sock *req)
 {
        struct sock *child = NULL;
        struct dccp_request_sock *dreq = dccp_rsk(req);
        if (child == NULL)
                goto listen_overflow;
 
-       inet_csk_reqsk_queue_unlink(sk, req, prev);
+       inet_csk_reqsk_queue_unlink(sk, req);
        inet_csk_reqsk_queue_removed(sk, req);
        inet_csk_reqsk_queue_add(sk, req, child);
 out:
        if (dccp_hdr(skb)->dccph_type != DCCP_PKT_RESET)
                req->rsk_ops->send_reset(sk, skb);
 
-       inet_csk_reqsk_queue_drop(sk, req, prev);
+       inet_csk_reqsk_queue_drop(sk, req);
        goto out;
 }
 
 
 #endif
 
 struct request_sock *inet_csk_search_req(const struct sock *sk,
-                                        struct request_sock ***prevp,
                                         const __be16 rport, const __be32 raddr,
                                         const __be32 laddr)
 {
        const struct inet_connection_sock *icsk = inet_csk(sk);
        struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt;
-       struct request_sock *req, **prev;
+       struct request_sock *req;
 
-       for (prev = &lopt->syn_table[inet_synq_hash(raddr, rport, lopt->hash_rnd,
-                                                   lopt->nr_table_entries)];
-            (req = *prev) != NULL;
-            prev = &req->dl_next) {
+       for (req = lopt->syn_table[inet_synq_hash(raddr, rport, lopt->hash_rnd,
+                                                 lopt->nr_table_entries)];
+            req != NULL;
+            req = req->dl_next) {
                const struct inet_request_sock *ireq = inet_rsk(req);
 
                if (ireq->ir_rmt_port == rport &&
                    ireq->ir_loc_addr == laddr &&
                    AF_INET_FAMILY(req->rsk_ops->family)) {
                        WARN_ON(req->sk);
-                       *prevp = prev;
                        break;
                }
        }
        i = lopt->clock_hand;
 
        do {
-               reqp=&lopt->syn_table[i];
+               reqp = &lopt->syn_table[i];
+               if (!*reqp)
+                       goto next_bucket;
+               write_lock(&queue->syn_wait_lock);
                while ((req = *reqp) != NULL) {
                        if (time_after_eq(now, req->expires)) {
                                int expire = 0, resend = 0;
                                }
 
                                /* Drop this request */
-                               inet_csk_reqsk_queue_unlink(parent, req, reqp);
+                               *reqp = req->dl_next;
                                reqsk_queue_removed(queue, req);
                                reqsk_put(req);
                                continue;
                        }
                        reqp = &req->dl_next;
                }
-
+               write_unlock(&queue->syn_wait_lock);
+next_bucket:
                i = (i + 1) & (lopt->nr_table_entries - 1);
 
        } while (--budget > 0);
 
                WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV &&
                    sk->sk_state != TCP_FIN_WAIT1);
 
-               if (tcp_check_req(sk, skb, req, NULL, true) == NULL)
+               if (tcp_check_req(sk, skb, req, true) == NULL)
                        goto discard;
        }
 
 
        }
 
        switch (sk->sk_state) {
-               struct request_sock *req, **prev;
+               struct request_sock *req;
        case TCP_LISTEN:
                if (sock_owned_by_user(sk))
                        goto out;
 
-               req = inet_csk_search_req(sk, &prev, th->dest,
+               req = inet_csk_search_req(sk, th->dest,
                                          iph->daddr, iph->saddr);
                if (!req)
                        goto out;
                 * created socket, and POSIX does not want network
                 * errors returned from accept().
                 */
-               inet_csk_reqsk_queue_drop(sk, req, prev);
+               inet_csk_reqsk_queue_drop(sk, req);
                NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
                goto out;
 
 
 static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
 {
-       struct tcphdr *th = tcp_hdr(skb);
+       const struct tcphdr *th = tcp_hdr(skb);
        const struct iphdr *iph = ip_hdr(skb);
+       struct request_sock *req;
        struct sock *nsk;
-       struct request_sock **prev;
-       /* Find possible connection requests. */
-       struct request_sock *req = inet_csk_search_req(sk, &prev, th->source,
-                                                      iph->saddr, iph->daddr);
+
+       req = inet_csk_search_req(sk, th->source, iph->saddr, iph->daddr);
        if (req)
-               return tcp_check_req(sk, skb, req, prev, false);
+               return tcp_check_req(sk, skb, req, false);
 
        nsk = inet_lookup_established(sock_net(sk), &tcp_hashinfo, iph->saddr,
                        th->source, iph->daddr, th->dest, inet_iif(skb));
 
 
 struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
                           struct request_sock *req,
-                          struct request_sock **prev,
                           bool fastopen)
 {
        struct tcp_options_received tmp_opt;
        if (child == NULL)
                goto listen_overflow;
 
-       inet_csk_reqsk_queue_unlink(sk, req, prev);
+       inet_csk_reqsk_queue_unlink(sk, req);
        inet_csk_reqsk_queue_removed(sk, req);
 
        inet_csk_reqsk_queue_add(sk, req, child);
                tcp_reset(sk);
        }
        if (!fastopen) {
-               inet_csk_reqsk_queue_drop(sk, req, prev);
+               inet_csk_reqsk_queue_drop(sk, req);
                NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_EMBRYONICRSTS);
        }
        return NULL;
 
 }
 
 struct request_sock *inet6_csk_search_req(const struct sock *sk,
-                                         struct request_sock ***prevp,
                                          const __be16 rport,
                                          const struct in6_addr *raddr,
                                          const struct in6_addr *laddr,
 {
        const struct inet_connection_sock *icsk = inet_csk(sk);
        struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt;
-       struct request_sock *req, **prev;
+       struct request_sock *req;
 
-       for (prev = &lopt->syn_table[inet6_synq_hash(raddr, rport,
+       for (req = lopt->syn_table[inet6_synq_hash(raddr, rport,
                                                     lopt->hash_rnd,
                                                     lopt->nr_table_entries)];
-            (req = *prev) != NULL;
-            prev = &req->dl_next) {
+            req != NULL;
+            req = req->dl_next) {
                const struct inet_request_sock *ireq = inet_rsk(req);
 
                if (ireq->ir_rmt_port == rport &&
                    ipv6_addr_equal(&ireq->ir_v6_loc_addr, laddr) &&
                    (!ireq->ir_iif || ireq->ir_iif == iif)) {
                        WARN_ON(req->sk != NULL);
-                       *prevp = prev;
                        return req;
                }
        }
 
 
        /* Might be for an request_sock */
        switch (sk->sk_state) {
-               struct request_sock *req, **prev;
+               struct request_sock *req;
        case TCP_LISTEN:
                if (sock_owned_by_user(sk))
                        goto out;
 
                /* Note : We use inet6_iif() here, not tcp_v6_iif() */
-               req = inet6_csk_search_req(sk, &prev, th->dest, &hdr->daddr,
+               req = inet6_csk_search_req(sk, th->dest, &hdr->daddr,
                                           &hdr->saddr, inet6_iif(skb));
                if (!req)
                        goto out;
                        goto out;
                }
 
-               inet_csk_reqsk_queue_drop(sk, req, prev);
+               inet_csk_reqsk_queue_drop(sk, req);
                NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
                goto out;
 
 
 static struct sock *tcp_v6_hnd_req(struct sock *sk, struct sk_buff *skb)
 {
-       struct request_sock *req, **prev;
        const struct tcphdr *th = tcp_hdr(skb);
+       struct request_sock *req;
        struct sock *nsk;
 
        /* Find possible connection requests. */
-       req = inet6_csk_search_req(sk, &prev, th->source,
+       req = inet6_csk_search_req(sk, th->source,
                                   &ipv6_hdr(skb)->saddr,
                                   &ipv6_hdr(skb)->daddr, tcp_v6_iif(skb));
        if (req)
-               return tcp_check_req(sk, skb, req, prev, false);
+               return tcp_check_req(sk, skb, req, false);
 
        nsk = __inet6_lookup_established(sock_net(sk), &tcp_hashinfo,
                                         &ipv6_hdr(skb)->saddr, th->source,