diff options
Diffstat (limited to 'net/ipv4/inet_timewait_sock.c')
-rw-r--r-- | net/ipv4/inet_timewait_sock.c | 35 |
1 files changed, 35 insertions, 0 deletions
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 | ||
411 | EXPORT_SYMBOL_GPL(inet_twdr_twcal_tick); | 411 | EXPORT_SYMBOL_GPL(inet_twdr_twcal_tick); |
412 | |||
413 | void 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); | ||
426 | restart: | ||
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 | } | ||
446 | EXPORT_SYMBOL_GPL(inet_twsk_purge); | ||