aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/inet_hashtables.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/inet_hashtables.c')
-rw-r--r--net/ipv4/inet_hashtables.c58
1 files changed, 48 insertions, 10 deletions
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index 48d45008f749..90f422c9447b 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -66,8 +66,9 @@ void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb,
66/* 66/*
67 * Get rid of any references to a local port held by the given sock. 67 * Get rid of any references to a local port held by the given sock.
68 */ 68 */
69static void __inet_put_port(struct inet_hashinfo *hashinfo, struct sock *sk) 69static void __inet_put_port(struct sock *sk)
70{ 70{
71 struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
71 const int bhash = inet_bhashfn(inet_sk(sk)->num, hashinfo->bhash_size); 72 const int bhash = inet_bhashfn(inet_sk(sk)->num, hashinfo->bhash_size);
72 struct inet_bind_hashbucket *head = &hashinfo->bhash[bhash]; 73 struct inet_bind_hashbucket *head = &hashinfo->bhash[bhash];
73 struct inet_bind_bucket *tb; 74 struct inet_bind_bucket *tb;
@@ -81,10 +82,10 @@ static void __inet_put_port(struct inet_hashinfo *hashinfo, struct sock *sk)
81 spin_unlock(&head->lock); 82 spin_unlock(&head->lock);
82} 83}
83 84
84void inet_put_port(struct inet_hashinfo *hashinfo, struct sock *sk) 85void inet_put_port(struct sock *sk)
85{ 86{
86 local_bh_disable(); 87 local_bh_disable();
87 __inet_put_port(hashinfo, sk); 88 __inet_put_port(sk);
88 local_bh_enable(); 89 local_bh_enable();
89} 90}
90 91
@@ -317,8 +318,9 @@ static inline u32 inet_sk_port_offset(const struct sock *sk)
317 inet->dport); 318 inet->dport);
318} 319}
319 320
320void __inet_hash_nolisten(struct inet_hashinfo *hashinfo, struct sock *sk) 321void __inet_hash_nolisten(struct sock *sk)
321{ 322{
323 struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
322 struct hlist_head *list; 324 struct hlist_head *list;
323 rwlock_t *lock; 325 rwlock_t *lock;
324 struct inet_ehash_bucket *head; 326 struct inet_ehash_bucket *head;
@@ -337,13 +339,14 @@ void __inet_hash_nolisten(struct inet_hashinfo *hashinfo, struct sock *sk)
337} 339}
338EXPORT_SYMBOL_GPL(__inet_hash_nolisten); 340EXPORT_SYMBOL_GPL(__inet_hash_nolisten);
339 341
340void __inet_hash(struct inet_hashinfo *hashinfo, struct sock *sk) 342static void __inet_hash(struct sock *sk)
341{ 343{
344 struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
342 struct hlist_head *list; 345 struct hlist_head *list;
343 rwlock_t *lock; 346 rwlock_t *lock;
344 347
345 if (sk->sk_state != TCP_LISTEN) { 348 if (sk->sk_state != TCP_LISTEN) {
346 __inet_hash_nolisten(hashinfo, sk); 349 __inet_hash_nolisten(sk);
347 return; 350 return;
348 } 351 }
349 352
@@ -357,13 +360,48 @@ void __inet_hash(struct inet_hashinfo *hashinfo, struct sock *sk)
357 write_unlock(lock); 360 write_unlock(lock);
358 wake_up(&hashinfo->lhash_wait); 361 wake_up(&hashinfo->lhash_wait);
359} 362}
360EXPORT_SYMBOL_GPL(__inet_hash); 363
364void inet_hash(struct sock *sk)
365{
366 if (sk->sk_state != TCP_CLOSE) {
367 local_bh_disable();
368 __inet_hash(sk);
369 local_bh_enable();
370 }
371}
372EXPORT_SYMBOL_GPL(inet_hash);
373
374void inet_unhash(struct sock *sk)
375{
376 rwlock_t *lock;
377 struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
378
379 if (sk_unhashed(sk))
380 goto out;
381
382 if (sk->sk_state == TCP_LISTEN) {
383 local_bh_disable();
384 inet_listen_wlock(hashinfo);
385 lock = &hashinfo->lhash_lock;
386 } else {
387 lock = inet_ehash_lockp(hashinfo, sk->sk_hash);
388 write_lock_bh(lock);
389 }
390
391 if (__sk_del_node_init(sk))
392 sock_prot_inuse_add(sk->sk_prot, -1);
393 write_unlock_bh(lock);
394out:
395 if (sk->sk_state == TCP_LISTEN)
396 wake_up(&hashinfo->lhash_wait);
397}
398EXPORT_SYMBOL_GPL(inet_unhash);
361 399
362int __inet_hash_connect(struct inet_timewait_death_row *death_row, 400int __inet_hash_connect(struct inet_timewait_death_row *death_row,
363 struct sock *sk, 401 struct sock *sk,
364 int (*check_established)(struct inet_timewait_death_row *, 402 int (*check_established)(struct inet_timewait_death_row *,
365 struct sock *, __u16, struct inet_timewait_sock **), 403 struct sock *, __u16, struct inet_timewait_sock **),
366 void (*hash)(struct inet_hashinfo *, struct sock *)) 404 void (*hash)(struct sock *sk))
367{ 405{
368 struct inet_hashinfo *hinfo = death_row->hashinfo; 406 struct inet_hashinfo *hinfo = death_row->hashinfo;
369 const unsigned short snum = inet_sk(sk)->num; 407 const unsigned short snum = inet_sk(sk)->num;
@@ -427,7 +465,7 @@ ok:
427 inet_bind_hash(sk, tb, port); 465 inet_bind_hash(sk, tb, port);
428 if (sk_unhashed(sk)) { 466 if (sk_unhashed(sk)) {
429 inet_sk(sk)->sport = htons(port); 467 inet_sk(sk)->sport = htons(port);
430 hash(hinfo, sk); 468 hash(sk);
431 } 469 }
432 spin_unlock(&head->lock); 470 spin_unlock(&head->lock);
433 471
@@ -444,7 +482,7 @@ ok:
444 tb = inet_csk(sk)->icsk_bind_hash; 482 tb = inet_csk(sk)->icsk_bind_hash;
445 spin_lock_bh(&head->lock); 483 spin_lock_bh(&head->lock);
446 if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) { 484 if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) {
447 hash(hinfo, sk); 485 hash(sk);
448 spin_unlock_bh(&head->lock); 486 spin_unlock_bh(&head->lock);
449 return 0; 487 return 0;
450 } else { 488 } else {