Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5a10ecec authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'tw_cleanups'



Eric Dumazet says:

====================
inet: timewait cleanups

Another round of patches to make tw handling simpler.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 8b58a398 dbe7faa4
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -205,8 +205,8 @@ void inet_put_port(struct sock *sk);

void inet_hashinfo_init(struct inet_hashinfo *h);

int __inet_hash_nolisten(struct sock *sk, struct inet_timewait_sock *tw);
int __inet_hash(struct sock *sk, struct inet_timewait_sock *tw);
void __inet_hash_nolisten(struct sock *sk, struct sock *osk);
void __inet_hash(struct sock *sk, struct sock *osk);
void inet_hash(struct sock *sk);
void inet_unhash(struct sock *sk);

+3 −5
Original line number Diff line number Diff line
@@ -100,9 +100,7 @@ static inline struct inet_timewait_sock *inet_twsk(const struct sock *sk)
void inet_twsk_free(struct inet_timewait_sock *tw);
void inet_twsk_put(struct inet_timewait_sock *tw);

int inet_twsk_unhash(struct inet_timewait_sock *tw);

int inet_twsk_bind_unhash(struct inet_timewait_sock *tw,
void inet_twsk_bind_unhash(struct inet_timewait_sock *tw,
			   struct inet_hashinfo *hashinfo);

struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk,
@@ -113,7 +111,7 @@ void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk,
			   struct inet_hashinfo *hashinfo);

void inet_twsk_schedule(struct inet_timewait_sock *tw, const int timeo);
void inet_twsk_deschedule(struct inet_timewait_sock *tw);
void inet_twsk_deschedule_put(struct inet_timewait_sock *tw);

void inet_twsk_purge(struct inet_hashinfo *hashinfo,
		     struct inet_timewait_death_row *twdr, int family);
+0 −3
Original line number Diff line number Diff line
@@ -33,9 +33,6 @@ static inline int twsk_unique(struct sock *sk, struct sock *sktw, void *twp)

static inline void twsk_destructor(struct sock *sk)
{
	BUG_ON(sk == NULL);
	BUG_ON(sk->sk_prot == NULL);
	BUG_ON(sk->sk_prot->twsk_prot == NULL);
	if (sk->sk_prot->twsk_prot->twsk_destructor != NULL)
		sk->sk_prot->twsk_prot->twsk_destructor(sk);
}
+12 −26
Original line number Diff line number Diff line
@@ -343,7 +343,6 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row,
	struct sock *sk2;
	const struct hlist_nulls_node *node;
	struct inet_timewait_sock *tw = NULL;
	int twrefcnt = 0;

	spin_lock(lock);

@@ -371,21 +370,17 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row,
	WARN_ON(!sk_unhashed(sk));
	__sk_nulls_add_node_rcu(sk, &head->chain);
	if (tw) {
		twrefcnt = inet_twsk_unhash(tw);
		sk_nulls_del_node_init_rcu((struct sock *)tw);
		NET_INC_STATS_BH(net, LINUX_MIB_TIMEWAITRECYCLED);
	}
	spin_unlock(lock);
	if (twrefcnt)
		inet_twsk_put(tw);
	sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);

	if (twp) {
		*twp = tw;
	} else if (tw) {
		/* Silly. Should hash-dance instead... */
		inet_twsk_deschedule(tw);

		inet_twsk_put(tw);
		inet_twsk_deschedule_put(tw);
	}
	return 0;

@@ -403,13 +398,12 @@ static u32 inet_sk_port_offset(const struct sock *sk)
					  inet->inet_dport);
}

int __inet_hash_nolisten(struct sock *sk, struct inet_timewait_sock *tw)
void __inet_hash_nolisten(struct sock *sk, struct sock *osk)
{
	struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo;
	struct hlist_nulls_head *list;
	struct inet_ehash_bucket *head;
	spinlock_t *lock;
	int twrefcnt = 0;

	WARN_ON(!sk_unhashed(sk));

@@ -420,23 +414,22 @@ int __inet_hash_nolisten(struct sock *sk, struct inet_timewait_sock *tw)

	spin_lock(lock);
	__sk_nulls_add_node_rcu(sk, list);
	if (tw) {
		WARN_ON(sk->sk_hash != tw->tw_hash);
		twrefcnt = inet_twsk_unhash(tw);
	if (osk) {
		WARN_ON(sk->sk_hash != osk->sk_hash);
		sk_nulls_del_node_init_rcu(osk);
	}
	spin_unlock(lock);
	sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
	return twrefcnt;
}
EXPORT_SYMBOL_GPL(__inet_hash_nolisten);

int __inet_hash(struct sock *sk, struct inet_timewait_sock *tw)
void __inet_hash(struct sock *sk, struct sock *osk)
{
	struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo;
	struct inet_listen_hashbucket *ilb;

	if (sk->sk_state != TCP_LISTEN)
		return __inet_hash_nolisten(sk, tw);
		return __inet_hash_nolisten(sk, osk);

	WARN_ON(!sk_unhashed(sk));
	ilb = &hashinfo->listening_hash[inet_sk_listen_hashfn(sk)];
@@ -445,7 +438,6 @@ int __inet_hash(struct sock *sk, struct inet_timewait_sock *tw)
	__sk_nulls_add_node_rcu(sk, &ilb->head);
	sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
	spin_unlock(&ilb->lock);
	return 0;
}
EXPORT_SYMBOL(__inet_hash);

@@ -492,7 +484,6 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
	struct inet_bind_bucket *tb;
	int ret;
	struct net *net = sock_net(sk);
	int twrefcnt = 1;

	if (!snum) {
		int i, remaining, low, high, port;
@@ -560,19 +551,14 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
		inet_bind_hash(sk, tb, port);
		if (sk_unhashed(sk)) {
			inet_sk(sk)->inet_sport = htons(port);
			twrefcnt += __inet_hash_nolisten(sk, tw);
			__inet_hash_nolisten(sk, (struct sock *)tw);
		}
		if (tw)
			twrefcnt += inet_twsk_bind_unhash(tw, hinfo);
			inet_twsk_bind_unhash(tw, hinfo);
		spin_unlock(&head->lock);

		if (tw) {
			inet_twsk_deschedule(tw);
			while (twrefcnt) {
				twrefcnt--;
				inet_twsk_put(tw);
			}
		}
		if (tw)
			inet_twsk_deschedule_put(tw);

		ret = 0;
		goto out;
+14 −41
Original line number Diff line number Diff line
@@ -17,28 +17,6 @@
#include <net/ip.h>


/**
 *	inet_twsk_unhash - unhash a timewait socket from established hash
 *	@tw: timewait socket
 *
 *	unhash a timewait socket from established hash, if hashed.
 *	ehash lock must be held by caller.
 *	Returns 1 if caller should call inet_twsk_put() after lock release.
 */
int inet_twsk_unhash(struct inet_timewait_sock *tw)
{
	if (hlist_nulls_unhashed(&tw->tw_node))
		return 0;

	hlist_nulls_del_rcu(&tw->tw_node);
	sk_nulls_node_init(&tw->tw_node);
	/*
	 * We cannot call inet_twsk_put() ourself under lock,
	 * caller must call it for us.
	 */
	return 1;
}

/**
 *	inet_twsk_bind_unhash - unhash a timewait socket from bind hash
 *	@tw: timewait socket
@@ -48,35 +26,29 @@ int inet_twsk_unhash(struct inet_timewait_sock *tw)
 *	bind hash lock must be held by caller.
 *	Returns 1 if caller should call inet_twsk_put() after lock release.
 */
int inet_twsk_bind_unhash(struct inet_timewait_sock *tw,
void inet_twsk_bind_unhash(struct inet_timewait_sock *tw,
			  struct inet_hashinfo *hashinfo)
{
	struct inet_bind_bucket *tb = tw->tw_tb;

	if (!tb)
		return 0;
		return;

	__hlist_del(&tw->tw_bind_node);
	tw->tw_tb = NULL;
	inet_bind_bucket_destroy(hashinfo->bind_bucket_cachep, tb);
	/*
	 * We cannot call inet_twsk_put() ourself under lock,
	 * caller must call it for us.
	 */
	return 1;
	__sock_put((struct sock *)tw);
}

/* Must be called with locally disabled BHs. */
static void inet_twsk_kill(struct inet_timewait_sock *tw)
{
	struct inet_hashinfo *hashinfo = tw->tw_dr->hashinfo;
	struct inet_bind_hashbucket *bhead;
	int refcnt;
	/* Unlink from established hashes. */
	spinlock_t *lock = inet_ehash_lockp(hashinfo, tw->tw_hash);
	struct inet_bind_hashbucket *bhead;

	spin_lock(lock);
	refcnt = inet_twsk_unhash(tw);
	sk_nulls_del_node_init_rcu((struct sock *)tw);
	spin_unlock(lock);

	/* Disassociate with bind bucket. */
@@ -84,11 +56,9 @@ static void inet_twsk_kill(struct inet_timewait_sock *tw)
			hashinfo->bhash_size)];

	spin_lock(&bhead->lock);
	refcnt += inet_twsk_bind_unhash(tw, hashinfo);
	inet_twsk_bind_unhash(tw, hashinfo);
	spin_unlock(&bhead->lock);

	BUG_ON(refcnt >= atomic_read(&tw->tw_refcnt));
	atomic_sub(refcnt, &tw->tw_refcnt);
	atomic_dec(&tw->tw_dr->tw_count);
	inet_twsk_put(tw);
}
@@ -235,13 +205,17 @@ EXPORT_SYMBOL_GPL(inet_twsk_alloc);
 * tcp_input.c to verify this.
 */

/* This is for handling early-kills of TIME_WAIT sockets. */
void inet_twsk_deschedule(struct inet_timewait_sock *tw)
/* This is for handling early-kills of TIME_WAIT sockets.
 * Warning : consume reference.
 * Caller should not access tw anymore.
 */
void inet_twsk_deschedule_put(struct inet_timewait_sock *tw)
{
	if (del_timer_sync(&tw->tw_timer))
		inet_twsk_kill(tw);
	inet_twsk_put(tw);
}
EXPORT_SYMBOL(inet_twsk_deschedule);
EXPORT_SYMBOL(inet_twsk_deschedule_put);

void inet_twsk_schedule(struct inet_timewait_sock *tw, const int timeo)
{
@@ -311,9 +285,8 @@ void inet_twsk_purge(struct inet_hashinfo *hashinfo,

			rcu_read_unlock();
			local_bh_disable();
			inet_twsk_deschedule(tw);
			inet_twsk_deschedule_put(tw);
			local_bh_enable();
			inet_twsk_put(tw);
			goto restart_rcu;
		}
		/* If the nulls value we got at the end of this lookup is
Loading