|
@@ -104,6 +104,7 @@ static inline void ct_write_unlock_bh(unsigned int key)
|
|
|
spin_unlock_bh(&__ip_vs_conntbl_lock_array[key&CT_LOCKARRAY_MASK].l);
|
|
|
}
|
|
|
|
|
|
+static void ip_vs_conn_expire(unsigned long data);
|
|
|
|
|
|
/*
|
|
|
* Returns hash value for IPVS connection entry
|
|
@@ -453,10 +454,16 @@ ip_vs_conn_out_get_proto(struct netns_ipvs *ipvs, int af,
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(ip_vs_conn_out_get_proto);
|
|
|
|
|
|
+static void __ip_vs_conn_put_notimer(struct ip_vs_conn *cp)
|
|
|
+{
|
|
|
+ __ip_vs_conn_put(cp);
|
|
|
+ ip_vs_conn_expire((unsigned long)cp);
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Put back the conn and restart its timer with its timeout
|
|
|
*/
|
|
|
-void ip_vs_conn_put(struct ip_vs_conn *cp)
|
|
|
+static void __ip_vs_conn_put_timer(struct ip_vs_conn *cp)
|
|
|
{
|
|
|
unsigned long t = (cp->flags & IP_VS_CONN_F_ONE_PACKET) ?
|
|
|
0 : cp->timeout;
|
|
@@ -465,6 +472,16 @@ void ip_vs_conn_put(struct ip_vs_conn *cp)
|
|
|
__ip_vs_conn_put(cp);
|
|
|
}
|
|
|
|
|
|
+void ip_vs_conn_put(struct ip_vs_conn *cp)
|
|
|
+{
|
|
|
+ if ((cp->flags & IP_VS_CONN_F_ONE_PACKET) &&
|
|
|
+ (atomic_read(&cp->refcnt) == 1) &&
|
|
|
+ !timer_pending(&cp->timer))
|
|
|
+ /* expire connection immediately */
|
|
|
+ __ip_vs_conn_put_notimer(cp);
|
|
|
+ else
|
|
|
+ __ip_vs_conn_put_timer(cp);
|
|
|
+}
|
|
|
|
|
|
/*
|
|
|
* Fill a no_client_port connection with a client port number
|
|
@@ -834,7 +851,10 @@ static void ip_vs_conn_expire(unsigned long data)
|
|
|
ip_vs_unbind_dest(cp);
|
|
|
if (cp->flags & IP_VS_CONN_F_NO_CPORT)
|
|
|
atomic_dec(&ip_vs_conn_no_cport_cnt);
|
|
|
- call_rcu(&cp->rcu_head, ip_vs_conn_rcu_free);
|
|
|
+ if (cp->flags & IP_VS_CONN_F_ONE_PACKET)
|
|
|
+ ip_vs_conn_rcu_free(&cp->rcu_head);
|
|
|
+ else
|
|
|
+ call_rcu(&cp->rcu_head, ip_vs_conn_rcu_free);
|
|
|
atomic_dec(&ipvs->conn_count);
|
|
|
return;
|
|
|
}
|
|
@@ -850,7 +870,7 @@ static void ip_vs_conn_expire(unsigned long data)
|
|
|
if (ipvs->sync_state & IP_VS_STATE_MASTER)
|
|
|
ip_vs_sync_conn(ipvs, cp, sysctl_sync_threshold(ipvs));
|
|
|
|
|
|
- ip_vs_conn_put(cp);
|
|
|
+ __ip_vs_conn_put_timer(cp);
|
|
|
}
|
|
|
|
|
|
/* Modify timer, so that it expires as soon as possible.
|