]> git.hungrycats.org Git - linux/commitdiff
o tcp: convert tcp_tw_bucket->tw_death* to hlist
authorArnaldo Carvalho de Melo <acme@conectiva.com.br>
Mon, 16 Jun 2003 12:44:17 +0000 (09:44 -0300)
committerArnaldo Carvalho de Melo <acme@conectiva.com.br>
Mon, 16 Jun 2003 12:44:17 +0000 (09:44 -0300)
include/net/tcp.h
net/ipv4/tcp_minisocks.c

index 69630979810eed1d916be8971b7f27d01f7d10cb..de9e55910b3b0e8afe0aac452b2513ae703eb4d6 100644 (file)
@@ -215,9 +215,7 @@ struct tcp_tw_bucket {
        long                    tw_ts_recent_stamp;
        unsigned long           tw_ttd;
        struct tcp_bind_bucket  *tw_tb;
-       struct tcp_tw_bucket    *tw_next_death;
-       struct tcp_tw_bucket    **tw_pprev_death;
-
+       struct hlist_node       tw_death_node;
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
        struct in6_addr         tw_v6_daddr;
        struct in6_addr         tw_v6_rcv_saddr;
@@ -236,9 +234,37 @@ static __inline__ void tw_add_bind_node(struct tcp_tw_bucket *tw,
        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) \
        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))
 
 extern kmem_cache_t *tcp_timewait_cachep;
index 3b499f2eaf3d32e9dbe2268d3d455225217cf03b..b0a6d0f166e07bb379544658c1ef51d9a376bfad 100644 (file)
@@ -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_ts_recent        = tp->ts_recent;
                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 (tw->tw_family == PF_INET6) {
@@ -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. */
-static int tcp_tw_death_row_slot = 0;
+static int tcp_tw_death_row_slot;
 
 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_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 struct timer_list tcp_tw_timer = TIMER_INITIALIZER(tcp_twkill, 0, 0);
 
 static void tcp_twkill(unsigned long dummy)
 {
        struct tcp_tw_bucket *tw;
+       struct hlist_node *node, *safe;
        int killed = 0;
 
        /* NOTE: compare this to previous version where lock
@@ -427,18 +428,13 @@ static void tcp_twkill(unsigned long dummy)
        if (tcp_tw_count == 0)
                goto out;
 
-       while((tw = tcp_tw_death_row[tcp_tw_death_row_slot]) != NULL) {
-               tcp_tw_death_row[tcp_tw_death_row_slot] = tw->tw_next_death;
-               if (tw->tw_next_death)
-                       tw->tw_next_death->tw_pprev_death = tw->tw_pprev_death;
-               tw->tw_pprev_death = NULL;
+       tw_for_each_inmate(tw, node, safe,
+                          &tcp_tw_death_row[tcp_tw_death_row_slot]) {
+               __tw_del_dead_node(tw);
                spin_unlock(&tw_death_lock);
-
                tcp_timewait_kill(tw);
                tcp_tw_put(tw);
-
                killed++;
-
                spin_lock(&tw_death_lock);
        }
        tcp_tw_death_row_slot =
@@ -459,11 +455,7 @@ out:
 void tcp_tw_deschedule(struct tcp_tw_bucket *tw)
 {
        spin_lock(&tw_death_lock);
-       if (tw->tw_pprev_death) {
-               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;
+       if (tw_del_dead_node(tw)) {
                tcp_tw_put(tw);
                if (--tcp_tw_count == 0)
                        del_timer(&tcp_tw_timer);
@@ -479,11 +471,11 @@ static int tcp_twcal_jiffie;
 static void tcp_twcal_tick(unsigned long);
 static struct timer_list tcp_twcal_timer =
                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)
 {
-       struct tcp_tw_bucket **tpp;
+       struct hlist_head *list;
        int slot;
 
        /* timeout := RTO * 3.5
@@ -515,13 +507,9 @@ void tcp_tw_schedule(struct tcp_tw_bucket *tw, int timeo)
        spin_lock(&tw_death_lock);
 
        /* Unlink it, if it was scheduled */
-       if (tw->tw_pprev_death) {
-               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;
+       if (tw_del_dead_node(tw))
                tcp_tw_count--;
-       else
+       else
                atomic_inc(&tw->tw_refcnt);
 
        if (slot >= TCP_TW_RECYCLE_SLOTS) {
@@ -535,7 +523,7 @@ void tcp_tw_schedule(struct tcp_tw_bucket *tw, int timeo)
                }
                tw->tw_ttd = jiffies + timeo;
                slot = (tcp_tw_death_row_slot + slot) & (TCP_TWKILL_SLOTS - 1);
-               tpp = &tcp_tw_death_row[slot];
+               list = &tcp_tw_death_row[slot];
        } else {
                tw->tw_ttd = jiffies + (slot << TCP_TW_RECYCLE_TICK);
 
@@ -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));
                        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)
-               (*tpp)->tw_pprev_death = &tw->tw_next_death;
-       *tpp = tw;
-       tw->tw_pprev_death = tpp;
+       hlist_add_head(&tw->tw_death_node, list);
 
        if (tcp_tw_count++ == 0)
                mod_timer(&tcp_tw_timer, jiffies+TCP_TWKILL_PERIOD);
@@ -579,12 +564,12 @@ void tcp_twcal_tick(unsigned long dummy)
 
        for (n=0; n<TCP_TW_RECYCLE_SLOTS; n++) {
                if (time_before_eq(j, now)) {
+                       struct hlist_node *node, *safe;
                        struct tcp_tw_bucket *tw;
 
-                       while((tw = tcp_twcal_row[slot]) != NULL) {
-                               tcp_twcal_row[slot] = tw->tw_next_death;
-                               tw->tw_pprev_death  = NULL;
-
+                       tw_for_each_inmate(tw, node, safe,
+                                          &tcp_twcal_row[slot]) {
+                               __tw_del_dead_node(tw);
                                tcp_timewait_kill(tw);
                                tcp_tw_put(tw);
                                killed++;
@@ -596,7 +581,7 @@ void tcp_twcal_tick(unsigned long dummy)
                                tcp_twcal_hand = slot;
                        }
 
-                       if (tcp_twcal_row[slot] != NULL) {
+                       if (!hlist_empty(&tcp_twcal_row[slot])) {
                                mod_timer(&tcp_twcal_timer, j);
                                goto out;
                        }