aboutsummaryrefslogtreecommitdiffstats
path: root/include/net/inet_hashtables.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/net/inet_hashtables.h')
-rw-r--r--include/net/inet_hashtables.h48
1 files changed, 48 insertions, 0 deletions
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index da07411b36d2..f5d65121f7b7 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -19,10 +19,14 @@
19#include <linux/list.h> 19#include <linux/list.h>
20#include <linux/slab.h> 20#include <linux/slab.h>
21#include <linux/spinlock.h> 21#include <linux/spinlock.h>
22#include <linux/tcp.h> /* only for TCP_LISTEN, damn :-( */
22#include <linux/types.h> 23#include <linux/types.h>
24#include <linux/wait.h>
23 25
24#include <net/sock.h> 26#include <net/sock.h>
25 27
28#include <asm/atomic.h>
29
26/* This is for all connections with a full identity, no wildcards. 30/* This is for all connections with a full identity, no wildcards.
27 * New scheme, half the table is for TIME_WAIT, the other half is 31 * New scheme, half the table is for TIME_WAIT, the other half is
28 * for the rest. I'll experiment with dynamic table growth later. 32 * for the rest. I'll experiment with dynamic table growth later.
@@ -192,4 +196,48 @@ static inline void inet_inherit_port(struct inet_hashinfo *table,
192 196
193extern void inet_put_port(struct inet_hashinfo *table, struct sock *sk); 197extern void inet_put_port(struct inet_hashinfo *table, struct sock *sk);
194 198
199extern void inet_listen_wlock(struct inet_hashinfo *hashinfo);
200
201/*
202 * - We may sleep inside this lock.
203 * - If sleeping is not required (or called from BH),
204 * use plain read_(un)lock(&inet_hashinfo.lhash_lock).
205 */
206static inline void inet_listen_lock(struct inet_hashinfo *hashinfo)
207{
208 /* read_lock synchronizes to candidates to writers */
209 read_lock(&hashinfo->lhash_lock);
210 atomic_inc(&hashinfo->lhash_users);
211 read_unlock(&hashinfo->lhash_lock);
212}
213
214static inline void inet_listen_unlock(struct inet_hashinfo *hashinfo)
215{
216 if (atomic_dec_and_test(&hashinfo->lhash_users))
217 wake_up(&hashinfo->lhash_wait);
218}
219
220static inline void __inet_hash(struct inet_hashinfo *hashinfo,
221 struct sock *sk, const int listen_possible)
222{
223 struct hlist_head *list;
224 rwlock_t *lock;
225
226 BUG_TRAP(sk_unhashed(sk));
227 if (listen_possible && sk->sk_state == TCP_LISTEN) {
228 list = &hashinfo->listening_hash[inet_sk_listen_hashfn(sk)];
229 lock = &hashinfo->lhash_lock;
230 inet_listen_wlock(hashinfo);
231 } else {
232 sk->sk_hashent = inet_sk_ehashfn(sk, hashinfo->ehash_size);
233 list = &hashinfo->ehash[sk->sk_hashent].chain;
234 lock = &hashinfo->ehash[sk->sk_hashent].lock;
235 write_lock(lock);
236 }
237 __sk_add_node(sk, list);
238 sock_prot_inc_use(sk->sk_prot);
239 write_unlock(lock);
240 if (listen_possible && sk->sk_state == TCP_LISTEN)
241 wake_up(&hashinfo->lhash_wait);
242}
195#endif /* _INET_HASHTABLES_H */ 243#endif /* _INET_HASHTABLES_H */