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 { |
