From: Amaury Denoyelle Date: Thu, 17 Sep 2026 09:54:41 +0000 (+0200) Subject: OPTIM/MINOR: server: restrict list usage X-Git-Tag: v3.5-dev9~22 X-Git-Url: https://git.kaiwu.me/?a=commitdiff_plain;h=be1974801ad890eccdc7aae847d2d23bc10be76b;p=haproxy.git OPTIM/MINOR: server: restrict list usage global list usage is pretty limited. It is only useful at postparsing to call srv_preinit() on each server instances. It is possible to simplify it in two ways. First, dynamic servers are not added anymore into it. For them, srv_preinit() is called directly on the "add server" handler. Then, servers are now removed from the global list once postparsing is over. Thus, is now never used during runtime. This allows to convert it from a mt-list to a simple list. Note that log servers and haload servers are created after check_config_validity(). They must be manually removed from . --- diff --git a/include/haproxy/server-t.h b/include/haproxy/server-t.h index 6e6288a21..4f8960923 100644 --- a/include/haproxy/server-t.h +++ b/include/haproxy/server-t.h @@ -351,7 +351,7 @@ struct server { signed char use_ssl; /* ssl enabled (1: on, 0: disabled, -1 forced off) */ unsigned int flags; /* server flags (SRV_F_*) */ unsigned int pp_opts; /* proxy protocol options (SRV_PP_*) */ - struct mt_list global_list; /* attach point in the global servers */ + struct list global_list; /* attach point in the global servers */ struct list el_px; /* attach point in parent proxy */ int cklen; /* the len of the cookie, to speed up checks */ int rdr_len; /* the length of the redirection prefix */ diff --git a/include/haproxy/server.h b/include/haproxy/server.h index 3c9667dfa..f4f8d9eda 100644 --- a/include/haproxy/server.h +++ b/include/haproxy/server.h @@ -44,7 +44,7 @@ extern struct idle_conns idle_conns[MAX_THREADS]; extern struct task *idle_conn_task[MAX_THREADS]; extern struct eb_root idle_conn_srv[MAX_THREADS]; -extern struct mt_list all_servers; +extern struct list all_servers; extern struct dict server_key_dict; int srv_downtime(const struct server *s); @@ -399,6 +399,12 @@ static inline void srv_detach(struct server *srv) struct proxy *px = srv->proxy; LIST_DEL_INIT(&srv->el_px); + + if (global.mode & MODE_STARTING) { + /* Necessary if startup is interrupted due to an early error before check_config_validity(). */ + LIST_DEL_INIT(&srv->global_list); + } + /* Reset the proxy's ready_srv if it was this one. */ HA_ATOMIC_CAS(&px->ready_srv, &srv, NULL); } diff --git a/src/cfgparse.c b/src/cfgparse.c index 81e52d871..5081dddbd 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -2287,8 +2287,7 @@ int check_config_validity() struct proxy *defpx; struct list *init_proxies_list = NULL; struct stktable *t; - struct server *newsrv = NULL, *defsrv; - struct mt_list back; + struct server *newsrv = NULL, *tmpsrv, *defsrv; int err_code = 0; /* Value forced to skip '1' due to an historical bug, see below for more details. */ unsigned int next_pxid = 2; @@ -2384,10 +2383,11 @@ int check_config_validity() * we must finish to initialize certain things on the servers, * as some of the fields may be accessed soon */ - MT_LIST_FOR_EACH_ENTRY_LOCKED(newsrv, &all_servers, global_list, back) { + list_for_each_entry_safe(newsrv, tmpsrv, &all_servers, global_list) { err_code |= srv_preinit(newsrv); if (err_code & ERR_CODE) goto out; + LIST_DEL_INIT(&newsrv->global_list); } list_for_each_entry(defpx, &defaults_list, el) { diff --git a/src/haload.c b/src/haload.c index 0cb9c922c..19b3c5328 100644 --- a/src/haload.c +++ b/src/haload.c @@ -2372,6 +2372,10 @@ static int hld_cfg_finalize(void) if (srv_preinit(srv)) goto leave; + + /* No need to stay in as srv_preinit() is manually called. */ + LIST_DEL_INIT(&srv->global_list); + #if 0 /* XXX Must this be done? XXX */ if (!srv_alloc_lb(srv, &hld_proxy)) { diff --git a/src/server.c b/src/server.c index d68ee1a59..211cb0209 100644 --- a/src/server.c +++ b/src/server.c @@ -79,7 +79,7 @@ struct srv_kw_list srv_keywords = { struct eb_root idle_conn_srv[MAX_THREADS]; struct task *idle_conn_task[MAX_THREADS] __read_mostly = {}; -struct mt_list all_servers = MT_LIST_HEAD_INIT(all_servers); +struct list all_servers = LIST_HEAD_INIT(all_servers); static struct task *server_atomic_sync_task = NULL; static event_hdl_async_equeue server_atomic_sync_queue; @@ -3159,10 +3159,9 @@ void srv_settings_cpy(struct server *srv, const struct server *src, int srv_tmpl } } -/* Allocates a server, attaches it to the global list - * and adds it to server list. Before deleting the server with - * srv_drop(), srv_detach() must be called to remove it from the parent - * proxy list +/* Allocates a server and adds it to server list. Before deleting the + * server with srv_drop(), srv_detach() must be called to remove it from the + * parent proxy list * * Returns the server on success, otherwise NULL. */ @@ -3179,7 +3178,6 @@ struct server *new_server(struct proxy *proxy) srv->obj_type = OBJ_TYPE_SERVER; srv->proxy = proxy; LIST_APPEND(&proxy->servers, &srv->el_px); - MT_LIST_APPEND(&all_servers, &srv->global_list); LIST_INIT(&srv->srv_rec_item); LIST_INIT(&srv->ip_rec_item); LIST_INIT(&srv->pp_tlvs); @@ -3211,6 +3209,10 @@ struct server *new_server(struct proxy *proxy) HA_RWLOCK_INIT(&srv->path_params.param_lock); + LIST_INIT(&srv->global_list); + if (global.mode & MODE_STARTING) + LIST_APPEND(&all_servers, &srv->global_list); + return srv; } @@ -3313,7 +3315,6 @@ void srv_drop(struct server *srv) HA_SPIN_DESTROY(&srv->lock); - MT_LIST_DELETE(&srv->global_list); event_hdl_sub_list_destroy(&srv->e_subs); srv_free(&srv); diff --git a/src/sink.c b/src/sink.c index 887f4e047..73d838ff4 100644 --- a/src/sink.c +++ b/src/sink.c @@ -1310,6 +1310,9 @@ struct sink *sink_new_from_logger(struct logger *logger) if (srv_preinit(srv) & ERR_CODE) goto error; + /* No need to stay in as srv_preinit() is manually called. */ + LIST_DEL_INIT(&srv->global_list); + /* Same thing for the forward proxy: check_config_validity() has * already walked over sink_proxies_list, so this one is never * initialized nor finalized. Keep the same order as there, as the