tcp: add memory barriers to write space paths
[linux-2.6-block.git] / net / ipv6 / inet6_connection_sock.c
index 29b32206e49488e1155900adfcd1707ea909855e..6927f3fb5597fd2013b885cddb35bed852b950d5 100644 (file)
@@ -112,22 +112,20 @@ static u32 inet6_synq_hash(const struct in6_addr *raddr, const __be16 rport,
        return c & (synq_hsize - 1);
 }
 
-struct request_sock *inet6_csk_search_req(const struct sock *sk,
-                                         struct request_sock ***prevp,
+struct request_sock *inet6_csk_search_req(struct sock *sk,
                                          const __be16 rport,
                                          const struct in6_addr *raddr,
                                          const struct in6_addr *laddr,
                                          const int iif)
 {
-       const struct inet_connection_sock *icsk = inet_csk(sk);
+       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;
+       u32 hash = inet6_synq_hash(raddr, rport, lopt->hash_rnd,
+                                  lopt->nr_table_entries);
 
-       for (prev = &lopt->syn_table[inet6_synq_hash(raddr, rport,
-                                                    lopt->hash_rnd,
-                                                    lopt->nr_table_entries)];
-            (req = *prev) != NULL;
-            prev = &req->dl_next) {
+       spin_lock(&icsk->icsk_accept_queue.syn_wait_lock);
+       for (req = lopt->syn_table[hash]; req != NULL; req = req->dl_next) {
                const struct inet_request_sock *ireq = inet_rsk(req);
 
                if (ireq->ir_rmt_port == rport &&
@@ -135,13 +133,14 @@ struct request_sock *inet6_csk_search_req(const struct sock *sk,
                    ipv6_addr_equal(&ireq->ir_v6_rmt_addr, raddr) &&
                    ipv6_addr_equal(&ireq->ir_v6_loc_addr, laddr) &&
                    (!ireq->ir_iif || ireq->ir_iif == iif)) {
+                       atomic_inc(&req->rsk_refcnt);
                        WARN_ON(req->sk != NULL);
-                       *prevp = prev;
-                       return req;
+                       break;
                }
        }
+       spin_unlock(&icsk->icsk_accept_queue.syn_wait_lock);
 
-       return NULL;
+       return req;
 }
 EXPORT_SYMBOL_GPL(inet6_csk_search_req);