From 9b3188786b35d9ce51d3e1d9a1816268c85b8d42 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 3 Dec 2009 00:49:01 +0000 Subject: [PATCH] --- yaml --- r: 172187 b: refs/heads/master c: 47e1c323069bcef0acb8a2b48921688573f5ca63 h: refs/heads/master i: 172185: f6070a256348a10f2a7ceee48892f32ce3cdfad8 172183: a8c31c4dc5184095f4ee17a8a590f2d129ad7295 v: v3 --- [refs] | 2 +- trunk/net/ipv4/inet_timewait_sock.c | 19 ++++++++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/[refs] b/[refs] index b70e0dc84cfb..557b50cd811b 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 13475a30b66cdb9250a34052c19ac98847373030 +refs/heads/master: 47e1c323069bcef0acb8a2b48921688573f5ca63 diff --git a/trunk/net/ipv4/inet_timewait_sock.c b/trunk/net/ipv4/inet_timewait_sock.c index 11a107a5af4f..0fdf45e4c90c 100644 --- a/trunk/net/ipv4/inet_timewait_sock.c +++ b/trunk/net/ipv4/inet_timewait_sock.c @@ -109,7 +109,6 @@ void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk, tw->tw_tb = icsk->icsk_bind_hash; WARN_ON(!icsk->icsk_bind_hash); inet_twsk_add_bind_node(tw, &tw->tw_tb->owners); - atomic_inc(&tw->tw_refcnt); spin_unlock(&bhead->lock); spin_lock(lock); @@ -119,13 +118,22 @@ void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk, * Should be done before removing sk from established chain * because readers are lockless and search established first. */ - atomic_inc(&tw->tw_refcnt); inet_twsk_add_node_rcu(tw, &ehead->twchain); /* Step 3: Remove SK from established hash. */ if (__sk_nulls_del_node_init_rcu(sk)) sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); + /* + * Notes : + * - We initially set tw_refcnt to 0 in inet_twsk_alloc() + * - We add one reference for the bhash link + * - We add one reference for the ehash link + * - We want this refcnt update done before allowing other + * threads to find this tw in ehash chain. + */ + atomic_add(1 + 1 + 1, &tw->tw_refcnt); + spin_unlock(lock); } @@ -157,7 +165,12 @@ struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, const int stat tw->tw_transparent = inet->transparent; tw->tw_prot = sk->sk_prot_creator; twsk_net_set(tw, hold_net(sock_net(sk))); - atomic_set(&tw->tw_refcnt, 1); + /* + * Because we use RCU lookups, we should not set tw_refcnt + * to a non null value before everything is setup for this + * timewait socket. + */ + atomic_set(&tw->tw_refcnt, 0); inet_twsk_dead_node_init(tw); __module_get(tw->tw_prot->owner); }