MINOR: server: shard by thread sess_conns member

Server member <sess_conns> is a mt_list which contains every backend
connections attached to a session which targets this server. These
connecions are not present in idle server trees.

The main utility of this list is to be able to cleanup these connections
prior to removing a server via "del server" CLI. However, this procedure
will be adjusted by a future patch. As such, <sess_conns> member must be
moved into srv_per_thread struct. Effectively, this duplicates a list
for every threads.

This commit does not introduce functional change. Its goal is to ensure
that these connections are now ordered by their owning thread, which
will allow to implement a purge, similarly to idle connections attached
to servers.
This commit is contained in:
Amaury Denoyelle 2025-08-14 18:18:01 +02:00
parent 37fca75ef7
commit f234b40cde
3 changed files with 25 additions and 22 deletions

View File

@ -266,6 +266,7 @@ struct srv_per_thread {
struct eb_root idle_conns; /* Shareable idle connections */
struct eb_root safe_conns; /* Safe idle connections */
struct eb_root avail_conns; /* Connections in use, but with still new streams available */
struct mt_list sess_conns; /* Connections attached to a session which cannot be shared across clients */
/* Secondary idle conn storage used in parallel to idle/safe trees.
* Used to sort them by last usage and purge them in reverse order.
@ -388,8 +389,6 @@ struct server {
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) */
struct mt_list sess_conns; /* list of private conns managed by a session on this server */
/* Element below are usd by LB algorithms and must be doable in
* parallel to other threads reusing connections above.
*/

View File

@ -3072,8 +3072,6 @@ struct server *new_server(struct proxy *proxy)
srv->agent.proxy = proxy;
srv->xprt = srv->check.xprt = srv->agent.xprt = xprt_get(XPRT_RAW);
MT_LIST_INIT(&srv->sess_conns);
guid_init(&srv->guid);
MT_LIST_INIT(&srv->watcher_list);
@ -5935,6 +5933,7 @@ static int srv_init_per_thr(struct server *srv)
srv->per_thr[i].idle_conns = EB_ROOT;
srv->per_thr[i].safe_conns = EB_ROOT;
srv->per_thr[i].avail_conns = EB_ROOT;
MT_LIST_INIT(&srv->per_thr[i].sess_conns);
MT_LIST_INIT(&srv->per_thr[i].streams);
LIST_INIT(&srv->per_thr[i].idle_conn_list);
@ -6428,29 +6427,34 @@ static int cli_parse_delete_server(char **args, char *payload, struct appctx *ap
BUG_ON(srv->curr_idle_conns);
/* Close idle private connections attached to this server. */
MT_LIST_FOR_EACH_ENTRY_LOCKED(sess_conns, &srv->sess_conns, srv_el, back) {
struct connection *conn, *conn_back;
list_for_each_entry_safe(conn, conn_back, &sess_conns->conn_list, sess_el) {
for (i = tid;;) {
MT_LIST_FOR_EACH_ENTRY_LOCKED(sess_conns, &srv->per_thr[i].sess_conns, srv_el, back) {
struct connection *conn, *conn_back;
list_for_each_entry_safe(conn, conn_back, &sess_conns->conn_list, sess_el) {
/* Only idle connections should be present if srv_check_for_deletion() is true. */
BUG_ON(!(conn->flags & CO_FL_SESS_IDLE));
--((struct session *)conn->owner)->idle_conns;
/* Only idle connections should be present if srv_check_for_deletion() is true. */
BUG_ON(!(conn->flags & CO_FL_SESS_IDLE));
--((struct session *)conn->owner)->idle_conns;
LIST_DEL_INIT(&conn->sess_el);
conn->owner = NULL;
LIST_DEL_INIT(&conn->sess_el);
conn->owner = NULL;
if (sess_conns->tid != tid) {
if (conn->mux && conn->mux->takeover)
conn->mux->takeover(conn, sess_conns->tid, 1);
else if (conn->xprt && conn->xprt->takeover)
conn->xprt->takeover(conn, conn->ctx, sess_conns->tid, 1);
if (sess_conns->tid != tid) {
if (conn->mux && conn->mux->takeover)
conn->mux->takeover(conn, sess_conns->tid, 1);
else if (conn->xprt && conn->xprt->takeover)
conn->xprt->takeover(conn, conn->ctx, sess_conns->tid, 1);
}
conn_release(conn);
}
conn_release(conn);
LIST_DELETE(&sess_conns->sess_el);
pool_free(pool_head_sess_priv_conns, sess_conns);
sess_conns = NULL;
}
LIST_DELETE(&sess_conns->sess_el);
pool_free(pool_head_sess_priv_conns, sess_conns);
sess_conns = NULL;
if ((i = ((i + 1 == global.nbthread) ? 0 : i + 1)) == tid)
break;
}
/* removing cannot fail anymore when we reach this:

View File

@ -617,7 +617,7 @@ static struct sess_priv_conns *sess_alloc_sess_conns(struct session *sess,
MT_LIST_INIT(&pconns->srv_el);
/* If <target> endpoint is a server, also attach storage element into it. */
if ((srv = objt_server(target)))
MT_LIST_APPEND(&srv->sess_conns, &pconns->srv_el);
MT_LIST_APPEND(&srv->per_thr[tid].sess_conns, &pconns->srv_el);
pconns->tid = tid;