aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/inet_timewait_sock.h3
-rw-r--r--net/ipv4/inet_timewait_sock.c35
-rw-r--r--net/ipv4/tcp_ipv4.c1
-rw-r--r--net/ipv6/tcp_ipv6.c1
4 files changed, 40 insertions, 0 deletions
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
index 95c660c9719b..91324908fccd 100644
--- a/include/net/inet_timewait_sock.h
+++ b/include/net/inet_timewait_sock.h
@@ -208,6 +208,9 @@ extern void inet_twsk_schedule(struct inet_timewait_sock *tw,
208extern void inet_twsk_deschedule(struct inet_timewait_sock *tw, 208extern void inet_twsk_deschedule(struct inet_timewait_sock *tw,
209 struct inet_timewait_death_row *twdr); 209 struct inet_timewait_death_row *twdr);
210 210
211extern void inet_twsk_purge(struct net *net, struct inet_hashinfo *hashinfo,
212 struct inet_timewait_death_row *twdr, int family);
213
211static inline 214static inline
212struct net *twsk_net(const struct inet_timewait_sock *twsk) 215struct net *twsk_net(const struct inet_timewait_sock *twsk)
213{ 216{
diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c
index d985bd613d25..743f011b9a84 100644
--- a/net/ipv4/inet_timewait_sock.c
+++ b/net/ipv4/inet_timewait_sock.c
@@ -409,3 +409,38 @@ out:
409} 409}
410 410
411EXPORT_SYMBOL_GPL(inet_twdr_twcal_tick); 411EXPORT_SYMBOL_GPL(inet_twdr_twcal_tick);
412
413void inet_twsk_purge(struct net *net, struct inet_hashinfo *hashinfo,
414 struct inet_timewait_death_row *twdr, int family)
415{
416 struct inet_timewait_sock *tw;
417 struct sock *sk;
418 struct hlist_node *node;
419 int h;
420
421 local_bh_disable();
422 for (h = 0; h < (hashinfo->ehash_size); h++) {
423 struct inet_ehash_bucket *head =
424 inet_ehash_bucket(hashinfo, h);
425 rwlock_t *lock = inet_ehash_lockp(hashinfo, h);
426restart:
427 write_lock(lock);
428 sk_for_each(sk, node, &head->twchain) {
429
430 tw = inet_twsk(sk);
431 if (!net_eq(twsk_net(tw), net) ||
432 tw->tw_family != family)
433 continue;
434
435 atomic_inc(&tw->tw_refcnt);
436 write_unlock(lock);
437 inet_twsk_deschedule(tw, twdr);
438 inet_twsk_put(tw);
439
440 goto restart;
441 }
442 write_unlock(lock);
443 }
444 local_bh_enable();
445}
446EXPORT_SYMBOL_GPL(inet_twsk_purge);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 44c1e934824b..1b4fee20fc93 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -2376,6 +2376,7 @@ static int __net_init tcp_sk_init(struct net *net)
2376static void __net_exit tcp_sk_exit(struct net *net) 2376static void __net_exit tcp_sk_exit(struct net *net)
2377{ 2377{
2378 inet_ctl_sock_destroy(net->ipv4.tcp_sock); 2378 inet_ctl_sock_destroy(net->ipv4.tcp_sock);
2379 inet_twsk_purge(net, &tcp_hashinfo, &tcp_death_row, AF_INET);
2379} 2380}
2380 2381
2381static struct pernet_operations __net_initdata tcp_sk_ops = { 2382static struct pernet_operations __net_initdata tcp_sk_ops = {
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 5b90b369ccb2..b585c850a89a 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -2148,6 +2148,7 @@ static int tcpv6_net_init(struct net *net)
2148static void tcpv6_net_exit(struct net *net) 2148static void tcpv6_net_exit(struct net *net)
2149{ 2149{
2150 inet_ctl_sock_destroy(net->ipv6.tcp_sk); 2150 inet_ctl_sock_destroy(net->ipv6.tcp_sk);
2151 inet_twsk_purge(net, &tcp_hashinfo, &tcp_death_row, AF_INET6);
2151} 2152}
2152 2153
2153static struct pernet_operations tcpv6_net_ops = { 2154static struct pernet_operations tcpv6_net_ops = {