Index: ip_vs.h =================================================================== RCS file: /home/wensong/cvsroot/ipvs/ip_vs.h,v retrieving revision 1.17 diff -u -r1.17 ip_vs.h --- ip_vs.h 2001/04/04 02:53:11 1.17 +++ ip_vs.h 2001/04/06 14:30:58 @@ -257,7 +257,8 @@ struct list_head c_list; /* hashed list heads */ atomic_t refcnt; /* reference count */ struct timer_list timer; /* Expiration timer */ - unsigned long timeout; /* timeout */ + + /* Protocol, addresses and port numbers */ __u32 caddr; /* client address */ __u32 vaddr; /* virtual address */ __u32 daddr; /* destination address */ @@ -265,11 +266,17 @@ __u16 vport; __u16 dport; __u16 protocol; /* Which protocol (TCP/UDP) */ - struct ip_vs_conn *control; /* Master control connection */ - atomic_t n_control; /* Number of controlled ones */ + + /* Flags and state transition */ + spinlock_t lock; /* lock for state transition */ __u16 flags; /* status flags */ __u16 state; /* state info */ - struct ip_vs_timeout_table *timeout_table; + unsigned long timeout; /* timeout */ + struct ip_vs_timeout_table *timeout_table; + + /* Control members */ + struct ip_vs_conn *control; /* Master control connection */ + atomic_t n_control; /* Number of controlled ones */ struct ip_vs_dest *dest; /* real server */ atomic_t in_pkts; /* incoming packet counter */ Index: ip_vs_conn.c =================================================================== RCS file: /home/wensong/cvsroot/ipvs/ip_vs_conn.c,v retrieving revision 1.14 diff -u -r1.14 ip_vs_conn.c --- ip_vs_conn.c 2001/04/04 02:53:11 1.14 +++ ip_vs_conn.c 2001/04/06 14:30:58 @@ -505,7 +505,6 @@ static inline int vs_set_state_timeout(struct ip_vs_conn *cp, int state) { struct ip_vs_timeout_table *vstim = cp->timeout_table; - int scale; /* * Use default timeout table if no specific for this entry @@ -514,13 +513,16 @@ vstim = &vs_timeout_table; cp->timeout = vstim->timeout[cp->state=state]; - scale = vstim->scale; - if (scale<0) - cp->timeout >>= -scale; - else if (scale > 0) - cp->timeout <<= scale; + if (vstim->scale) { + int scale = vstim->scale; + if (scale<0) + cp->timeout >>= -scale; + else if (scale > 0) + cp->timeout <<= scale; + } + return state; } @@ -592,15 +594,22 @@ int ip_vs_set_state(struct ip_vs_conn *cp, int state_off, struct iphdr *iph, void *tp) { - switch (iph->protocol) { - case IPPROTO_ICMP: - return vs_set_state_timeout(cp, IP_VS_S_ICMP); - case IPPROTO_UDP: - return vs_set_state_timeout(cp, IP_VS_S_UDP); - case IPPROTO_TCP: - return vs_tcp_state(cp, state_off, tp); - } - return -1; + int ret; + + spin_lock(&cp->lock); + switch (iph->protocol) { + case IPPROTO_ICMP: + ret = vs_set_state_timeout(cp, IP_VS_S_ICMP); + case IPPROTO_UDP: + ret = vs_set_state_timeout(cp, IP_VS_S_UDP); + case IPPROTO_TCP: + ret = vs_tcp_state(cp, state_off, tp); + default: + ret = -1; + } + spin_unlock(&cp->lock); + + return ret; } @@ -1207,60 +1216,58 @@ static void ip_vs_conn_expire(unsigned long data) { - struct ip_vs_conn *cp = (struct ip_vs_conn *)data; + struct ip_vs_conn *cp = (struct ip_vs_conn *)data; - if (cp->timeout_table) + if (cp->timeout_table) cp->timeout = cp->timeout_table->timeout[IP_VS_S_TIME_WAIT]; else cp->timeout = vs_timeout_table.timeout[IP_VS_S_TIME_WAIT]; - - /* - * hey, I'm using it - */ - atomic_inc(&cp->refcnt); - /* - * do I control anybody? - */ - if (atomic_read(&cp->n_control)) - goto expire_later; + /* + * hey, I'm using it + */ + atomic_inc(&cp->refcnt); - /* - * does anybody controls me? - */ - if (cp->control) - ip_vs_control_del(cp); + /* + * do I control anybody? + */ + if (atomic_read(&cp->n_control)) + goto expire_later; - /* - * unhash it if it is hashed in the conn table - */ + /* + * unhash it if it is hashed in the conn table + */ ip_vs_conn_unhash(cp); - /* - * refcnt==1 implies I'm the only one referrer - */ - if (atomic_read(&cp->refcnt) == 1) { + /* + * refcnt==1 implies I'm the only one referrer + */ + if (atomic_read(&cp->refcnt) == 1) { /* make sure that there is no timer on it now */ if (timer_pending(&cp->timer)) del_sltimer(&cp->timer); + /* does anybody control me? */ + if (cp->control) + ip_vs_control_del(cp); + ip_vs_unbind_dest(cp); ip_vs_unbind_app(cp); - ip_vs_timeout_detach(cp); + ip_vs_timeout_detach(cp); if (cp->flags & IP_VS_CONN_F_NO_CPORT) atomic_dec(&ip_vs_conn_no_cport_cnt); - kmem_cache_free(ip_vs_conn_cachep, cp); - /* sysctl_ip_always_defrag--; */ - MOD_DEC_USE_COUNT; - goto expire_out; - } + kmem_cache_free(ip_vs_conn_cachep, cp); + /* sysctl_ip_always_defrag--; */ + MOD_DEC_USE_COUNT; + goto expire_out; + } expire_later: - IP_VS_DBG(7, "delayed: refcnt-1=%d conn.n_control=%d\n", + IP_VS_DBG(7, "delayed: refcnt-1=%d conn.n_control=%d\n", atomic_read(&cp->refcnt)-1, atomic_read(&cp->n_control)); - ip_vs_conn_put(cp); + ip_vs_conn_put(cp); expire_out: } @@ -1299,6 +1306,7 @@ cp->flags = flags; cp->app_data = NULL; cp->control = NULL; + cp->lock = SPIN_LOCK_UNLOCKED; atomic_set(&cp->n_control, 0); atomic_set(&cp->in_pkts, 0);