diff --git a/include/haproxy/server-t.h b/include/haproxy/server-t.h index 85dcd63da..dd76ffac6 100644 --- a/include/haproxy/server-t.h +++ b/include/haproxy/server-t.h @@ -388,6 +388,7 @@ struct server { unsigned int curr_total_conns; /* Current number of total connections to the server, used or idle, only calculated if strict-maxconn is used */ unsigned int max_used_conns; /* Max number of used connections (the counter is reset at each connection purges */ unsigned int est_need_conns; /* Estimate on the number of needed connections (max of curr and previous max_used) */ + unsigned int curr_sess_idle_conns; /* Current number of idle connections attached to a session instead of idle/safe trees. */ /* Element below are usd by LB algorithms and must be doable in * parallel to other threads reusing connections above. diff --git a/src/connection.c b/src/connection.c index d1faf6f2a..4f0b5c342 100644 --- a/src/connection.c +++ b/src/connection.c @@ -540,10 +540,9 @@ static void conn_backend_deinit(struct connection *conn) if (obj_type(conn->target) == OBJ_TYPE_SERVER) { struct server *srv = __objt_server(conn->target); - /* If the connection is not private, it is accounted by the server. */ - if (!(conn->flags & CO_FL_PRIVATE)) { + if (!(conn->flags & CO_FL_PRIVATE) || (conn->flags & CO_FL_SESS_IDLE)) srv_release_conn(srv, conn); - } + if (srv->flags & SRV_F_STRICT_MAXCONN) _HA_ATOMIC_DEC(&srv->curr_total_conns); } diff --git a/src/server.c b/src/server.c index 9c120171f..6599e53d7 100644 --- a/src/server.c +++ b/src/server.c @@ -7251,7 +7251,11 @@ static void srv_cleanup_connections(struct server *srv) /* removes an idle conn after updating the server idle conns counters */ void srv_release_conn(struct server *srv, struct connection *conn) { - if (conn->flags & CO_FL_LIST_MASK) { + if (conn->flags & CO_FL_SESS_IDLE) { + _HA_ATOMIC_DEC(&srv->curr_sess_idle_conns); + conn->flags &= ~CO_FL_SESS_IDLE; + } + else if (conn->flags & CO_FL_LIST_MASK) { /* The connection is currently in the server's idle list, so tell it * there's one less connection available in that list. */ diff --git a/src/session.c b/src/session.c index 43e54dc5e..103fb159a 100644 --- a/src/session.c +++ b/src/session.c @@ -139,7 +139,6 @@ void session_free(struct session *sess) list_for_each_entry_safe(conn, conn_back, &pconns->conn_list, sess_el) { LIST_DEL_INIT(&conn->sess_el); conn->owner = NULL; - conn->flags &= ~CO_FL_SESS_IDLE; LIST_APPEND(&conn_tmp_list, &conn->sess_el); } MT_LIST_DELETE(&pconns->srv_el); @@ -732,6 +731,9 @@ int session_reinsert_idle_conn(struct session *sess, struct connection *conn) /* Check that session is able to keep idle connection . This must * be called each time a connection stored in a session becomes idle. * + * If can be kept as idle in the session, idle sess conn counter of its + * target server will be incremented. + * * Returns 0 if the connection is kept, else non-zero if the connection was * explicitely removed from session. */ @@ -758,6 +760,8 @@ int session_check_idle_conn(struct session *sess, struct connection *conn) else { conn->flags |= CO_FL_SESS_IDLE; sess->idle_conns++; + if (srv) + HA_ATOMIC_INC(&srv->curr_sess_idle_conns); } return 0; @@ -771,6 +775,7 @@ struct connection *session_get_conn(struct session *sess, void *target, int64_t { struct connection *srv_conn, *res = NULL; struct sess_priv_conns *pconns; + struct server *srv; HA_SPIN_LOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock); @@ -787,6 +792,10 @@ struct connection *session_get_conn(struct session *sess, void *target, int64_t if (srv_conn->flags & CO_FL_SESS_IDLE) { srv_conn->flags &= ~CO_FL_SESS_IDLE; sess->idle_conns--; + + srv = objt_server(srv_conn->target); + if (srv) + HA_ATOMIC_DEC(&srv->curr_sess_idle_conns); } res = srv_conn;