Merge branch 'locks' of git://linux-nfs.org/~bfields/linux
[sfrench/cifs-2.6.git] / include / net / inet_hashtables.h
index 37f6cb11212723f7f2094a16b6cec92bbe9ef670..48ac620cb8463db035dd93b36d82ea34d2ad05ec 100644 (file)
@@ -74,6 +74,7 @@ struct inet_ehash_bucket {
  * ports are created in O(1) time?  I thought so. ;-)  -DaveM
  */
 struct inet_bind_bucket {
+       struct net              *ib_net;
        unsigned short          port;
        signed short            fastreuse;
        struct hlist_node       node;
@@ -194,6 +195,7 @@ static inline void inet_ehash_locks_free(struct inet_hashinfo *hashinfo)
 
 extern struct inet_bind_bucket *
                    inet_bind_bucket_create(struct kmem_cache *cachep,
+                                           struct net *net,
                                            struct inet_bind_hashbucket *head,
                                            const unsigned short snum);
 extern void inet_bind_bucket_destroy(struct kmem_cache *cachep,
@@ -219,9 +221,9 @@ static inline int inet_sk_listen_hashfn(const struct sock *sk)
 }
 
 /* Caller must disable local BH processing. */
-static inline void __inet_inherit_port(struct inet_hashinfo *table,
-                                      struct sock *sk, struct sock *child)
+static inline void __inet_inherit_port(struct sock *sk, struct sock *child)
 {
+       struct inet_hashinfo *table = sk->sk_prot->hashinfo;
        const int bhash = inet_bhashfn(inet_sk(child)->num, table->bhash_size);
        struct inet_bind_hashbucket *head = &table->bhash[bhash];
        struct inet_bind_bucket *tb;
@@ -233,15 +235,14 @@ static inline void __inet_inherit_port(struct inet_hashinfo *table,
        spin_unlock(&head->lock);
 }
 
-static inline void inet_inherit_port(struct inet_hashinfo *table,
-                                    struct sock *sk, struct sock *child)
+static inline void inet_inherit_port(struct sock *sk, struct sock *child)
 {
        local_bh_disable();
-       __inet_inherit_port(table, sk, child);
+       __inet_inherit_port(sk, child);
        local_bh_enable();
 }
 
-extern void inet_put_port(struct inet_hashinfo *table, struct sock *sk);
+extern void inet_put_port(struct sock *sk);
 
 extern void inet_listen_wlock(struct inet_hashinfo *hashinfo);
 
@@ -264,74 +265,21 @@ static inline void inet_listen_unlock(struct inet_hashinfo *hashinfo)
                wake_up(&hashinfo->lhash_wait);
 }
 
-static inline void __inet_hash(struct inet_hashinfo *hashinfo,
-                              struct sock *sk, const int listen_possible)
-{
-       struct hlist_head *list;
-       rwlock_t *lock;
-
-       BUG_TRAP(sk_unhashed(sk));
-       if (listen_possible && sk->sk_state == TCP_LISTEN) {
-               list = &hashinfo->listening_hash[inet_sk_listen_hashfn(sk)];
-               lock = &hashinfo->lhash_lock;
-               inet_listen_wlock(hashinfo);
-       } else {
-               struct inet_ehash_bucket *head;
-               sk->sk_hash = inet_sk_ehashfn(sk);
-               head = inet_ehash_bucket(hashinfo, sk->sk_hash);
-               list = &head->chain;
-               lock = inet_ehash_lockp(hashinfo, sk->sk_hash);
-               write_lock(lock);
-       }
-       __sk_add_node(sk, list);
-       sock_prot_inc_use(sk->sk_prot);
-       write_unlock(lock);
-       if (listen_possible && sk->sk_state == TCP_LISTEN)
-               wake_up(&hashinfo->lhash_wait);
-}
-
-static inline void inet_hash(struct inet_hashinfo *hashinfo, struct sock *sk)
-{
-       if (sk->sk_state != TCP_CLOSE) {
-               local_bh_disable();
-               __inet_hash(hashinfo, sk, 1);
-               local_bh_enable();
-       }
-}
-
-static inline void inet_unhash(struct inet_hashinfo *hashinfo, struct sock *sk)
-{
-       rwlock_t *lock;
-
-       if (sk_unhashed(sk))
-               goto out;
-
-       if (sk->sk_state == TCP_LISTEN) {
-               local_bh_disable();
-               inet_listen_wlock(hashinfo);
-               lock = &hashinfo->lhash_lock;
-       } else {
-               lock = inet_ehash_lockp(hashinfo, sk->sk_hash);
-               write_lock_bh(lock);
-       }
-
-       if (__sk_del_node_init(sk))
-               sock_prot_dec_use(sk->sk_prot);
-       write_unlock_bh(lock);
-out:
-       if (sk->sk_state == TCP_LISTEN)
-               wake_up(&hashinfo->lhash_wait);
-}
+extern void __inet_hash_nolisten(struct sock *sk);
+extern void inet_hash(struct sock *sk);
+extern void inet_unhash(struct sock *sk);
 
-extern struct sock *__inet_lookup_listener(struct inet_hashinfo *hashinfo,
+extern struct sock *__inet_lookup_listener(struct net *net,
+                                          struct inet_hashinfo *hashinfo,
                                           const __be32 daddr,
                                           const unsigned short hnum,
                                           const int dif);
 
-static inline struct sock *inet_lookup_listener(struct inet_hashinfo *hashinfo,
-                                               __be32 daddr, __be16 dport, int dif)
+static inline struct sock *inet_lookup_listener(struct net *net,
+               struct inet_hashinfo *hashinfo,
+               __be32 daddr, __be16 dport, int dif)
 {
-       return __inet_lookup_listener(hashinfo, daddr, ntohs(dport), dif);
+       return __inet_lookup_listener(net, hashinfo, daddr, ntohs(dport), dif);
 }
 
 /* Socket demux engine toys. */
@@ -365,26 +313,26 @@ typedef __u64 __bitwise __addrpair;
                                   (((__force __u64)(__be32)(__daddr)) << 32) | \
                                   ((__force __u64)(__be32)(__saddr)));
 #endif /* __BIG_ENDIAN */
-#define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
-       (((__sk)->sk_hash == (__hash))                          &&      \
+#define INET_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
+       (((__sk)->sk_hash == (__hash)) && ((__sk)->sk_net == (__net))   &&      \
         ((*((__addrpair *)&(inet_sk(__sk)->daddr))) == (__cookie))     &&      \
         ((*((__portpair *)&(inet_sk(__sk)->dport))) == (__ports))      &&      \
         (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
-#define INET_TW_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
-       (((__sk)->sk_hash == (__hash))                          &&      \
+#define INET_TW_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
+       (((__sk)->sk_hash == (__hash)) && ((__sk)->sk_net == (__net))   &&      \
         ((*((__addrpair *)&(inet_twsk(__sk)->tw_daddr))) == (__cookie)) &&     \
         ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) &&      \
         (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
 #else /* 32-bit arch */
 #define INET_ADDR_COOKIE(__name, __saddr, __daddr)
-#define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)   \
-       (((__sk)->sk_hash == (__hash))                          &&      \
+#define INET_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif)    \
+       (((__sk)->sk_hash == (__hash)) && ((__sk)->sk_net == (__net))   &&      \
         (inet_sk(__sk)->daddr          == (__saddr))           &&      \
         (inet_sk(__sk)->rcv_saddr      == (__daddr))           &&      \
         ((*((__portpair *)&(inet_sk(__sk)->dport))) == (__ports))      &&      \
         (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
-#define INET_TW_MATCH(__sk, __hash,__cookie, __saddr, __daddr, __ports, __dif) \
-       (((__sk)->sk_hash == (__hash))                          &&      \
+#define INET_TW_MATCH(__sk, __net, __hash,__cookie, __saddr, __daddr, __ports, __dif)  \
+       (((__sk)->sk_hash == (__hash)) && ((__sk)->sk_net == (__net))   &&      \
         (inet_twsk(__sk)->tw_daddr     == (__saddr))           &&      \
         (inet_twsk(__sk)->tw_rcv_saddr == (__daddr))           &&      \
         ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) &&      \
@@ -397,66 +345,36 @@ typedef __u64 __bitwise __addrpair;
  *
  * Local BH must be disabled here.
  */
-static inline struct sock *
-       __inet_lookup_established(struct inet_hashinfo *hashinfo,
-                                 const __be32 saddr, const __be16 sport,
-                                 const __be32 daddr, const u16 hnum,
-                                 const int dif)
-{
-       INET_ADDR_COOKIE(acookie, saddr, daddr)
-       const __portpair ports = INET_COMBINED_PORTS(sport, hnum);
-       struct sock *sk;
-       const struct hlist_node *node;
-       /* Optimize here for direct hit, only listening connections can
-        * have wildcards anyways.
-        */
-       unsigned int hash = inet_ehashfn(daddr, hnum, saddr, sport);
-       struct inet_ehash_bucket *head = inet_ehash_bucket(hashinfo, hash);
-       rwlock_t *lock = inet_ehash_lockp(hashinfo, hash);
-
-       prefetch(head->chain.first);
-       read_lock(lock);
-       sk_for_each(sk, node, &head->chain) {
-               if (INET_MATCH(sk, hash, acookie, saddr, daddr, ports, dif))
-                       goto hit; /* You sunk my battleship! */
-       }
-
-       /* Must check for a TIME_WAIT'er before going to listener hash. */
-       sk_for_each(sk, node, &head->twchain) {
-               if (INET_TW_MATCH(sk, hash, acookie, saddr, daddr, ports, dif))
-                       goto hit;
-       }
-       sk = NULL;
-out:
-       read_unlock(lock);
-       return sk;
-hit:
-       sock_hold(sk);
-       goto out;
-}
+extern struct sock * __inet_lookup_established(struct net *net,
+               struct inet_hashinfo *hashinfo,
+               const __be32 saddr, const __be16 sport,
+               const __be32 daddr, const u16 hnum, const int dif);
 
 static inline struct sock *
-       inet_lookup_established(struct inet_hashinfo *hashinfo,
+       inet_lookup_established(struct net *net, struct inet_hashinfo *hashinfo,
                                const __be32 saddr, const __be16 sport,
                                const __be32 daddr, const __be16 dport,
                                const int dif)
 {
-       return __inet_lookup_established(hashinfo, saddr, sport, daddr,
+       return __inet_lookup_established(net, hashinfo, saddr, sport, daddr,
                                         ntohs(dport), dif);
 }
 
-static inline struct sock *__inet_lookup(struct inet_hashinfo *hashinfo,
+static inline struct sock *__inet_lookup(struct net *net,
+                                        struct inet_hashinfo *hashinfo,
                                         const __be32 saddr, const __be16 sport,
                                         const __be32 daddr, const __be16 dport,
                                         const int dif)
 {
        u16 hnum = ntohs(dport);
-       struct sock *sk = __inet_lookup_established(hashinfo, saddr, sport, daddr,
-                                                   hnum, dif);
-       return sk ? : __inet_lookup_listener(hashinfo, daddr, hnum, dif);
+       struct sock *sk = __inet_lookup_established(net, hashinfo,
+                               saddr, sport, daddr, hnum, dif);
+
+       return sk ? : __inet_lookup_listener(net, hashinfo, daddr, hnum, dif);
 }
 
-static inline struct sock *inet_lookup(struct inet_hashinfo *hashinfo,
+static inline struct sock *inet_lookup(struct net *net,
+                                      struct inet_hashinfo *hashinfo,
                                       const __be32 saddr, const __be16 sport,
                                       const __be32 daddr, const __be16 dport,
                                       const int dif)
@@ -464,12 +382,17 @@ static inline struct sock *inet_lookup(struct inet_hashinfo *hashinfo,
        struct sock *sk;
 
        local_bh_disable();
-       sk = __inet_lookup(hashinfo, saddr, sport, daddr, dport, dif);
+       sk = __inet_lookup(net, hashinfo, saddr, sport, daddr, dport, dif);
        local_bh_enable();
 
        return sk;
 }
 
+extern int __inet_hash_connect(struct inet_timewait_death_row *death_row,
+               struct sock *sk,
+               int (*check_established)(struct inet_timewait_death_row *,
+                       struct sock *, __u16, struct inet_timewait_sock **),
+                              void (*hash)(struct sock *sk));
 extern int inet_hash_connect(struct inet_timewait_death_row *death_row,
                             struct sock *sk);
 #endif /* _INET_HASHTABLES_H */