aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/inet_timewait_sock.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/inet_timewait_sock.c')
-rw-r--r--net/ipv4/inet_timewait_sock.c61
1 files changed, 42 insertions, 19 deletions
diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c
index 0fdf45e4c90c..cc94cc2d8b2d 100644
--- a/net/ipv4/inet_timewait_sock.c
+++ b/net/ipv4/inet_timewait_sock.c
@@ -15,9 +15,13 @@
15#include <net/ip.h> 15#include <net/ip.h>
16 16
17 17
18/* 18/**
19 * unhash a timewait socket from established hash 19 * inet_twsk_unhash - unhash a timewait socket from established hash
20 * lock must be hold by caller 20 * @tw: timewait socket
21 *
22 * unhash a timewait socket from established hash, if hashed.
23 * ehash lock must be held by caller.
24 * Returns 1 if caller should call inet_twsk_put() after lock release.
21 */ 25 */
22int inet_twsk_unhash(struct inet_timewait_sock *tw) 26int inet_twsk_unhash(struct inet_timewait_sock *tw)
23{ 27{
@@ -26,6 +30,37 @@ int inet_twsk_unhash(struct inet_timewait_sock *tw)
26 30
27 hlist_nulls_del_rcu(&tw->tw_node); 31 hlist_nulls_del_rcu(&tw->tw_node);
28 sk_nulls_node_init(&tw->tw_node); 32 sk_nulls_node_init(&tw->tw_node);
33 /*
34 * We cannot call inet_twsk_put() ourself under lock,
35 * caller must call it for us.
36 */
37 return 1;
38}
39
40/**
41 * inet_twsk_bind_unhash - unhash a timewait socket from bind hash
42 * @tw: timewait socket
43 * @hashinfo: hashinfo pointer
44 *
45 * unhash a timewait socket from bind hash, if hashed.
46 * bind hash lock must be held by caller.
47 * Returns 1 if caller should call inet_twsk_put() after lock release.
48 */
49int inet_twsk_bind_unhash(struct inet_timewait_sock *tw,
50 struct inet_hashinfo *hashinfo)
51{
52 struct inet_bind_bucket *tb = tw->tw_tb;
53
54 if (!tb)
55 return 0;
56
57 __hlist_del(&tw->tw_bind_node);
58 tw->tw_tb = NULL;
59 inet_bind_bucket_destroy(hashinfo->bind_bucket_cachep, tb);
60 /*
61 * We cannot call inet_twsk_put() ourself under lock,
62 * caller must call it for us.
63 */
29 return 1; 64 return 1;
30} 65}
31 66
@@ -34,7 +69,6 @@ static void __inet_twsk_kill(struct inet_timewait_sock *tw,
34 struct inet_hashinfo *hashinfo) 69 struct inet_hashinfo *hashinfo)
35{ 70{
36 struct inet_bind_hashbucket *bhead; 71 struct inet_bind_hashbucket *bhead;
37 struct inet_bind_bucket *tb;
38 int refcnt; 72 int refcnt;
39 /* Unlink from established hashes. */ 73 /* Unlink from established hashes. */
40 spinlock_t *lock = inet_ehash_lockp(hashinfo, tw->tw_hash); 74 spinlock_t *lock = inet_ehash_lockp(hashinfo, tw->tw_hash);
@@ -46,15 +80,11 @@ static void __inet_twsk_kill(struct inet_timewait_sock *tw,
46 /* Disassociate with bind bucket. */ 80 /* Disassociate with bind bucket. */
47 bhead = &hashinfo->bhash[inet_bhashfn(twsk_net(tw), tw->tw_num, 81 bhead = &hashinfo->bhash[inet_bhashfn(twsk_net(tw), tw->tw_num,
48 hashinfo->bhash_size)]; 82 hashinfo->bhash_size)];
83
49 spin_lock(&bhead->lock); 84 spin_lock(&bhead->lock);
50 tb = tw->tw_tb; 85 refcnt += inet_twsk_bind_unhash(tw, hashinfo);
51 if (tb) {
52 __hlist_del(&tw->tw_bind_node);
53 tw->tw_tb = NULL;
54 inet_bind_bucket_destroy(hashinfo->bind_bucket_cachep, tb);
55 refcnt++;
56 }
57 spin_unlock(&bhead->lock); 86 spin_unlock(&bhead->lock);
87
58#ifdef SOCK_REFCNT_DEBUG 88#ifdef SOCK_REFCNT_DEBUG
59 if (atomic_read(&tw->tw_refcnt) != 1) { 89 if (atomic_read(&tw->tw_refcnt) != 1) {
60 printk(KERN_DEBUG "%s timewait_sock %p refcnt=%d\n", 90 printk(KERN_DEBUG "%s timewait_sock %p refcnt=%d\n",
@@ -126,7 +156,7 @@ void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk,
126 156
127 /* 157 /*
128 * Notes : 158 * Notes :
129 * - We initially set tw_refcnt to 0 in inet_twsk_alloc() 159 * - We initially set tw_refcnt to 0 in inet_twsk_alloc()
130 * - We add one reference for the bhash link 160 * - We add one reference for the bhash link
131 * - We add one reference for the ehash link 161 * - We add one reference for the ehash link
132 * - We want this refcnt update done before allowing other 162 * - We want this refcnt update done before allowing other
@@ -136,7 +166,6 @@ void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk,
136 166
137 spin_unlock(lock); 167 spin_unlock(lock);
138} 168}
139
140EXPORT_SYMBOL_GPL(__inet_twsk_hashdance); 169EXPORT_SYMBOL_GPL(__inet_twsk_hashdance);
141 170
142struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, const int state) 171struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, const int state)
@@ -177,7 +206,6 @@ struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, const int stat
177 206
178 return tw; 207 return tw;
179} 208}
180
181EXPORT_SYMBOL_GPL(inet_twsk_alloc); 209EXPORT_SYMBOL_GPL(inet_twsk_alloc);
182 210
183/* Returns non-zero if quota exceeded. */ 211/* Returns non-zero if quota exceeded. */
@@ -256,7 +284,6 @@ void inet_twdr_hangman(unsigned long data)
256out: 284out:
257 spin_unlock(&twdr->death_lock); 285 spin_unlock(&twdr->death_lock);
258} 286}
259
260EXPORT_SYMBOL_GPL(inet_twdr_hangman); 287EXPORT_SYMBOL_GPL(inet_twdr_hangman);
261 288
262void inet_twdr_twkill_work(struct work_struct *work) 289void inet_twdr_twkill_work(struct work_struct *work)
@@ -287,7 +314,6 @@ void inet_twdr_twkill_work(struct work_struct *work)
287 spin_unlock_bh(&twdr->death_lock); 314 spin_unlock_bh(&twdr->death_lock);
288 } 315 }
289} 316}
290
291EXPORT_SYMBOL_GPL(inet_twdr_twkill_work); 317EXPORT_SYMBOL_GPL(inet_twdr_twkill_work);
292 318
293/* These are always called from BH context. See callers in 319/* These are always called from BH context. See callers in
@@ -307,7 +333,6 @@ void inet_twsk_deschedule(struct inet_timewait_sock *tw,
307 spin_unlock(&twdr->death_lock); 333 spin_unlock(&twdr->death_lock);
308 __inet_twsk_kill(tw, twdr->hashinfo); 334 __inet_twsk_kill(tw, twdr->hashinfo);
309} 335}
310
311EXPORT_SYMBOL(inet_twsk_deschedule); 336EXPORT_SYMBOL(inet_twsk_deschedule);
312 337
313void inet_twsk_schedule(struct inet_timewait_sock *tw, 338void inet_twsk_schedule(struct inet_timewait_sock *tw,
@@ -388,7 +413,6 @@ void inet_twsk_schedule(struct inet_timewait_sock *tw,
388 mod_timer(&twdr->tw_timer, jiffies + twdr->period); 413 mod_timer(&twdr->tw_timer, jiffies + twdr->period);
389 spin_unlock(&twdr->death_lock); 414 spin_unlock(&twdr->death_lock);
390} 415}
391
392EXPORT_SYMBOL_GPL(inet_twsk_schedule); 416EXPORT_SYMBOL_GPL(inet_twsk_schedule);
393 417
394void inet_twdr_twcal_tick(unsigned long data) 418void inet_twdr_twcal_tick(unsigned long data)
@@ -449,7 +473,6 @@ out:
449#endif 473#endif
450 spin_unlock(&twdr->death_lock); 474 spin_unlock(&twdr->death_lock);
451} 475}
452
453EXPORT_SYMBOL_GPL(inet_twdr_twcal_tick); 476EXPORT_SYMBOL_GPL(inet_twdr_twcal_tick);
454 477
455void inet_twsk_purge(struct inet_hashinfo *hashinfo, 478void inet_twsk_purge(struct inet_hashinfo *hashinfo,