diff options
Diffstat (limited to 'net/ipv4/inet_hashtables.c')
-rw-r--r-- | net/ipv4/inet_hashtables.c | 58 |
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 | */ |
69 | static void __inet_put_port(struct inet_hashinfo *hashinfo, struct sock *sk) | 69 | static 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 | ||
84 | void inet_put_port(struct inet_hashinfo *hashinfo, struct sock *sk) | 85 | void 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 | ||
320 | void __inet_hash_nolisten(struct inet_hashinfo *hashinfo, struct sock *sk) | 321 | void __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 | } |
338 | EXPORT_SYMBOL_GPL(__inet_hash_nolisten); | 340 | EXPORT_SYMBOL_GPL(__inet_hash_nolisten); |
339 | 341 | ||
340 | void __inet_hash(struct inet_hashinfo *hashinfo, struct sock *sk) | 342 | static 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 | } |
360 | EXPORT_SYMBOL_GPL(__inet_hash); | 363 | |
364 | void 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 | } | ||
372 | EXPORT_SYMBOL_GPL(inet_hash); | ||
373 | |||
374 | void 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); | ||
394 | out: | ||
395 | if (sk->sk_state == TCP_LISTEN) | ||
396 | wake_up(&hashinfo->lhash_wait); | ||
397 | } | ||
398 | EXPORT_SYMBOL_GPL(inet_unhash); | ||
361 | 399 | ||
362 | int __inet_hash_connect(struct inet_timewait_death_row *death_row, | 400 | int __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 { |