diff -ur v2.4.25/linux/net/ipv4/ipvs/ip_vs_conn.c linux/net/ipv4/ipvs/ip_vs_conn.c --- v2.4.25/linux/net/ipv4/ipvs/ip_vs_conn.c 2003-11-28 22:04:14.000000000 +0200 +++ linux/net/ipv4/ipvs/ip_vs_conn.c 2004-03-13 11:23:34.598986048 +0200 @@ -142,20 +142,19 @@ { unsigned hash; - if (cp->flags & IP_VS_CONN_F_HASHED) { - IP_VS_ERR("ip_vs_conn_hash(): request for already hashed, " - "called from %p\n", __builtin_return_address(0)); - return 0; - } - /* Hash by protocol, client address and port */ hash = ip_vs_conn_hashkey(cp->protocol, cp->caddr, cp->cport); ct_write_lock(hash); - list_add(&cp->c_list, &ip_vs_conn_tab[hash]); - cp->flags |= IP_VS_CONN_F_HASHED; - atomic_inc(&cp->refcnt); + if (!(cp->flags & IP_VS_CONN_F_HASHED)) { + list_add(&cp->c_list, &ip_vs_conn_tab[hash]); + cp->flags |= IP_VS_CONN_F_HASHED; + atomic_inc(&cp->refcnt); + } else { + IP_VS_ERR("ip_vs_conn_hash(): request for already hashed, " + "called from %p\n", __builtin_return_address(0)); + } ct_write_unlock(hash); @@ -170,24 +169,23 @@ static int ip_vs_conn_unhash(struct ip_vs_conn *cp) { unsigned hash; - - if (!(cp->flags & IP_VS_CONN_F_HASHED)) { - IP_VS_ERR("ip_vs_conn_unhash(): request for unhash flagged, " - "called from %p\n", __builtin_return_address(0)); - return 0; - } + int ret; /* unhash it and decrease its reference counter */ hash = ip_vs_conn_hashkey(cp->protocol, cp->caddr, cp->cport); ct_write_lock(hash); - list_del(&cp->c_list); - cp->flags &= ~IP_VS_CONN_F_HASHED; - atomic_dec(&cp->refcnt); + if (cp->flags & IP_VS_CONN_F_HASHED) { + list_del(&cp->c_list); + cp->flags &= ~IP_VS_CONN_F_HASHED; + atomic_dec(&cp->refcnt); + ret = 1; + } else + ret = 0; ct_write_unlock(hash); - return 1; + return ret; } @@ -726,14 +724,16 @@ * Check if it is no_cport connection ... */ if (cp->flags & IP_VS_CONN_F_NO_CPORT) { - atomic_dec(&ip_vs_conn_no_cport_cnt); - ip_vs_conn_unhash(cp); - cp->flags &= ~IP_VS_CONN_F_NO_CPORT; - cp->cport = h.portp[0]; - /* hash on new dport */ - ip_vs_conn_hash(cp); - - IP_VS_DBG(10, "filled cport=%d\n", ntohs(cp->dport)); + if (ip_vs_conn_unhash(cp)) { + if (cp->flags & IP_VS_CONN_F_NO_CPORT) { + atomic_dec(&ip_vs_conn_no_cport_cnt); + cp->flags &= ~IP_VS_CONN_F_NO_CPORT; + cp->cport = h.portp[0]; + IP_VS_DBG(10, "filled cport=%d\n", ntohs(cp->dport)); + } + /* hash on new dport */ + ip_vs_conn_hash(cp); + } } if (!(rt = __ip_vs_get_out_rt(cp, RT_TOS(iph->tos)))) @@ -1142,11 +1142,12 @@ /* * Invalidate the connection template */ - ip_vs_conn_unhash(ct); - ct->dport = 65535; - ct->vport = 65535; - ct->cport = 0; - ip_vs_conn_hash(ct); + if (ct->cport && ip_vs_conn_unhash(ct)) { + ct->dport = 65535; + ct->vport = 65535; + ct->cport = 0; + ip_vs_conn_hash(ct); + } /* * Simply decrease the refcnt of the template, @@ -1200,7 +1201,8 @@ /* * unhash it if it is hashed in the conn table */ - ip_vs_conn_unhash(cp); + if (!ip_vs_conn_unhash(cp)) + goto expire_later; /* * refcnt==1 implies I'm the only one referrer