o tcp: convert tcp_tw_bucket->tw_death* to hlist

parent 1de6794f
...@@ -215,9 +215,7 @@ struct tcp_tw_bucket { ...@@ -215,9 +215,7 @@ struct tcp_tw_bucket {
long tw_ts_recent_stamp; long tw_ts_recent_stamp;
unsigned long tw_ttd; unsigned long tw_ttd;
struct tcp_bind_bucket *tw_tb; struct tcp_bind_bucket *tw_tb;
struct tcp_tw_bucket *tw_next_death; struct hlist_node tw_death_node;
struct tcp_tw_bucket **tw_pprev_death;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
struct in6_addr tw_v6_daddr; struct in6_addr tw_v6_daddr;
struct in6_addr tw_v6_rcv_saddr; struct in6_addr tw_v6_rcv_saddr;
...@@ -236,9 +234,37 @@ static __inline__ void tw_add_bind_node(struct tcp_tw_bucket *tw, ...@@ -236,9 +234,37 @@ static __inline__ void tw_add_bind_node(struct tcp_tw_bucket *tw,
hlist_add_head(&tw->tw_bind_node, list); hlist_add_head(&tw->tw_bind_node, list);
} }
static inline int tw_dead_hashed(struct tcp_tw_bucket *tw)
{
return tw->tw_death_node.pprev != NULL;
}
static __inline__ void tw_dead_node_init(struct tcp_tw_bucket *tw)
{
tw->tw_death_node.pprev = NULL;
}
static __inline__ void __tw_del_dead_node(struct tcp_tw_bucket *tw)
{
__hlist_del(&tw->tw_death_node);
tw_dead_node_init(tw);
}
static __inline__ int tw_del_dead_node(struct tcp_tw_bucket *tw)
{
if (tw_dead_hashed(tw)) {
__tw_del_dead_node(tw);
return 1;
}
return 0;
}
#define tw_for_each(tw, node, head) \ #define tw_for_each(tw, node, head) \
hlist_for_each_entry(tw, node, head, tw_node) hlist_for_each_entry(tw, node, head, tw_node)
#define tw_for_each_inmate(tw, node, safe, jail) \
hlist_for_each_entry_safe(tw, node, safe, jail, tw_death_node)
#define tcptw_sk(__sk) ((struct tcp_tw_bucket *)(__sk)) #define tcptw_sk(__sk) ((struct tcp_tw_bucket *)(__sk))
extern kmem_cache_t *tcp_timewait_cachep; extern kmem_cache_t *tcp_timewait_cachep;
......
...@@ -358,7 +358,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) ...@@ -358,7 +358,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
tw->tw_rcv_wnd = tcp_receive_window(tp); tw->tw_rcv_wnd = tcp_receive_window(tp);
tw->tw_ts_recent = tp->ts_recent; tw->tw_ts_recent = tp->ts_recent;
tw->tw_ts_recent_stamp = tp->ts_recent_stamp; tw->tw_ts_recent_stamp = tp->ts_recent_stamp;
tw->tw_pprev_death = NULL; tw_dead_node_init(tw);
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
if (tw->tw_family == PF_INET6) { if (tw->tw_family == PF_INET6) {
...@@ -399,7 +399,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) ...@@ -399,7 +399,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
} }
/* Kill off TIME_WAIT sockets once their lifetime has expired. */ /* Kill off TIME_WAIT sockets once their lifetime has expired. */
static int tcp_tw_death_row_slot = 0; static int tcp_tw_death_row_slot;
static void tcp_twkill(unsigned long); static void tcp_twkill(unsigned long);
...@@ -407,13 +407,14 @@ static void tcp_twkill(unsigned long); ...@@ -407,13 +407,14 @@ static void tcp_twkill(unsigned long);
#define TCP_TWKILL_SLOTS 8 /* Please keep this a power of 2. */ #define TCP_TWKILL_SLOTS 8 /* Please keep this a power of 2. */
#define TCP_TWKILL_PERIOD (TCP_TIMEWAIT_LEN/TCP_TWKILL_SLOTS) #define TCP_TWKILL_PERIOD (TCP_TIMEWAIT_LEN/TCP_TWKILL_SLOTS)
static struct tcp_tw_bucket *tcp_tw_death_row[TCP_TWKILL_SLOTS]; static struct hlist_head tcp_tw_death_row[TCP_TWKILL_SLOTS];
static spinlock_t tw_death_lock = SPIN_LOCK_UNLOCKED; static spinlock_t tw_death_lock = SPIN_LOCK_UNLOCKED;
static struct timer_list tcp_tw_timer = TIMER_INITIALIZER(tcp_twkill, 0, 0); static struct timer_list tcp_tw_timer = TIMER_INITIALIZER(tcp_twkill, 0, 0);
static void tcp_twkill(unsigned long dummy) static void tcp_twkill(unsigned long dummy)
{ {
struct tcp_tw_bucket *tw; struct tcp_tw_bucket *tw;
struct hlist_node *node, *safe;
int killed = 0; int killed = 0;
/* NOTE: compare this to previous version where lock /* NOTE: compare this to previous version where lock
...@@ -427,18 +428,13 @@ static void tcp_twkill(unsigned long dummy) ...@@ -427,18 +428,13 @@ static void tcp_twkill(unsigned long dummy)
if (tcp_tw_count == 0) if (tcp_tw_count == 0)
goto out; goto out;
while((tw = tcp_tw_death_row[tcp_tw_death_row_slot]) != NULL) { tw_for_each_inmate(tw, node, safe,
tcp_tw_death_row[tcp_tw_death_row_slot] = tw->tw_next_death; &tcp_tw_death_row[tcp_tw_death_row_slot]) {
if (tw->tw_next_death) __tw_del_dead_node(tw);
tw->tw_next_death->tw_pprev_death = tw->tw_pprev_death;
tw->tw_pprev_death = NULL;
spin_unlock(&tw_death_lock); spin_unlock(&tw_death_lock);
tcp_timewait_kill(tw); tcp_timewait_kill(tw);
tcp_tw_put(tw); tcp_tw_put(tw);
killed++; killed++;
spin_lock(&tw_death_lock); spin_lock(&tw_death_lock);
} }
tcp_tw_death_row_slot = tcp_tw_death_row_slot =
...@@ -459,11 +455,7 @@ static void tcp_twkill(unsigned long dummy) ...@@ -459,11 +455,7 @@ static void tcp_twkill(unsigned long dummy)
void tcp_tw_deschedule(struct tcp_tw_bucket *tw) void tcp_tw_deschedule(struct tcp_tw_bucket *tw)
{ {
spin_lock(&tw_death_lock); spin_lock(&tw_death_lock);
if (tw->tw_pprev_death) { if (tw_del_dead_node(tw)) {
if (tw->tw_next_death)
tw->tw_next_death->tw_pprev_death = tw->tw_pprev_death;
*tw->tw_pprev_death = tw->tw_next_death;
tw->tw_pprev_death = NULL;
tcp_tw_put(tw); tcp_tw_put(tw);
if (--tcp_tw_count == 0) if (--tcp_tw_count == 0)
del_timer(&tcp_tw_timer); del_timer(&tcp_tw_timer);
...@@ -479,11 +471,11 @@ static int tcp_twcal_jiffie; ...@@ -479,11 +471,11 @@ static int tcp_twcal_jiffie;
static void tcp_twcal_tick(unsigned long); static void tcp_twcal_tick(unsigned long);
static struct timer_list tcp_twcal_timer = static struct timer_list tcp_twcal_timer =
TIMER_INITIALIZER(tcp_twcal_tick, 0, 0); TIMER_INITIALIZER(tcp_twcal_tick, 0, 0);
static struct tcp_tw_bucket *tcp_twcal_row[TCP_TW_RECYCLE_SLOTS]; static struct hlist_head tcp_twcal_row[TCP_TW_RECYCLE_SLOTS];
void tcp_tw_schedule(struct tcp_tw_bucket *tw, int timeo) void tcp_tw_schedule(struct tcp_tw_bucket *tw, int timeo)
{ {
struct tcp_tw_bucket **tpp; struct hlist_head *list;
int slot; int slot;
/* timeout := RTO * 3.5 /* timeout := RTO * 3.5
...@@ -515,13 +507,9 @@ void tcp_tw_schedule(struct tcp_tw_bucket *tw, int timeo) ...@@ -515,13 +507,9 @@ void tcp_tw_schedule(struct tcp_tw_bucket *tw, int timeo)
spin_lock(&tw_death_lock); spin_lock(&tw_death_lock);
/* Unlink it, if it was scheduled */ /* Unlink it, if it was scheduled */
if (tw->tw_pprev_death) { if (tw_del_dead_node(tw))
if (tw->tw_next_death)
tw->tw_next_death->tw_pprev_death = tw->tw_pprev_death;
*tw->tw_pprev_death = tw->tw_next_death;
tw->tw_pprev_death = NULL;
tcp_tw_count--; tcp_tw_count--;
} else else
atomic_inc(&tw->tw_refcnt); atomic_inc(&tw->tw_refcnt);
if (slot >= TCP_TW_RECYCLE_SLOTS) { if (slot >= TCP_TW_RECYCLE_SLOTS) {
...@@ -535,7 +523,7 @@ void tcp_tw_schedule(struct tcp_tw_bucket *tw, int timeo) ...@@ -535,7 +523,7 @@ void tcp_tw_schedule(struct tcp_tw_bucket *tw, int timeo)
} }
tw->tw_ttd = jiffies + timeo; tw->tw_ttd = jiffies + timeo;
slot = (tcp_tw_death_row_slot + slot) & (TCP_TWKILL_SLOTS - 1); slot = (tcp_tw_death_row_slot + slot) & (TCP_TWKILL_SLOTS - 1);
tpp = &tcp_tw_death_row[slot]; list = &tcp_tw_death_row[slot];
} else { } else {
tw->tw_ttd = jiffies + (slot << TCP_TW_RECYCLE_TICK); tw->tw_ttd = jiffies + (slot << TCP_TW_RECYCLE_TICK);
...@@ -549,13 +537,10 @@ void tcp_tw_schedule(struct tcp_tw_bucket *tw, int timeo) ...@@ -549,13 +537,10 @@ void tcp_tw_schedule(struct tcp_tw_bucket *tw, int timeo)
mod_timer(&tcp_twcal_timer, jiffies + (slot<<TCP_TW_RECYCLE_TICK)); mod_timer(&tcp_twcal_timer, jiffies + (slot<<TCP_TW_RECYCLE_TICK));
slot = (tcp_twcal_hand + slot)&(TCP_TW_RECYCLE_SLOTS-1); slot = (tcp_twcal_hand + slot)&(TCP_TW_RECYCLE_SLOTS-1);
} }
tpp = &tcp_twcal_row[slot]; list = &tcp_twcal_row[slot];
} }
if ((tw->tw_next_death = *tpp) != NULL) hlist_add_head(&tw->tw_death_node, list);
(*tpp)->tw_pprev_death = &tw->tw_next_death;
*tpp = tw;
tw->tw_pprev_death = tpp;
if (tcp_tw_count++ == 0) if (tcp_tw_count++ == 0)
mod_timer(&tcp_tw_timer, jiffies+TCP_TWKILL_PERIOD); mod_timer(&tcp_tw_timer, jiffies+TCP_TWKILL_PERIOD);
...@@ -579,12 +564,12 @@ void tcp_twcal_tick(unsigned long dummy) ...@@ -579,12 +564,12 @@ void tcp_twcal_tick(unsigned long dummy)
for (n=0; n<TCP_TW_RECYCLE_SLOTS; n++) { for (n=0; n<TCP_TW_RECYCLE_SLOTS; n++) {
if (time_before_eq(j, now)) { if (time_before_eq(j, now)) {
struct hlist_node *node, *safe;
struct tcp_tw_bucket *tw; struct tcp_tw_bucket *tw;
while((tw = tcp_twcal_row[slot]) != NULL) { tw_for_each_inmate(tw, node, safe,
tcp_twcal_row[slot] = tw->tw_next_death; &tcp_twcal_row[slot]) {
tw->tw_pprev_death = NULL; __tw_del_dead_node(tw);
tcp_timewait_kill(tw); tcp_timewait_kill(tw);
tcp_tw_put(tw); tcp_tw_put(tw);
killed++; killed++;
...@@ -596,7 +581,7 @@ void tcp_twcal_tick(unsigned long dummy) ...@@ -596,7 +581,7 @@ void tcp_twcal_tick(unsigned long dummy)
tcp_twcal_hand = slot; tcp_twcal_hand = slot;
} }
if (tcp_twcal_row[slot] != NULL) { if (!hlist_empty(&tcp_twcal_row[slot])) {
mod_timer(&tcp_twcal_timer, j); mod_timer(&tcp_twcal_timer, j);
goto out; goto out;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment