]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MAJOR: proxy: convert proxies_list to a doubly linked struct list
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 16 Jan 2026 08:26:56 +0000 (09:26 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 23 Jul 2026 14:03:20 +0000 (16:03 +0200)
Frontend, backend and listen proxies are all stored in <proxies_list>
which contain all user visible entries. This list is read in several
places, for example during stats dump.

Dynamic backend have just been introduced in the previous 3.4 release,
with creation and removal of new instances at runtime. The main
bottleneck of these operation is the manipulation of <proxies_list> due
to its singly linked nature.

This patch converts <proxies_list> into a doubly linked standard list
type. Proxy member <el> is reused as attach point. It is already used
for internal proxies in other list, not intersecting with this usage.
The main benefit of this change is to improve performance for add and
delete backend operations. It is labelled as major as it may break
external components which manipulate this list.

Also, old naming <proxies_list> has been replaced by <main_proxies>.
This helps to differentiate with the already existing superset <proxies>
list which contain all proxies instances, even internal ones. In the
future, it should be sufficient to only keep the latter list. However,
this requires careful code analysis, in particular to ensure proxies
iteration are always executed with the proper capabilities filter.

Proxies reversal on post parsing has been updated to use the new list
format. This will be removed in a latter patch as it is now possible to
insert proxies in the order of their parsing in constant time. Most of
the other changes are straightforward : for/while statements are
replaced by list_for_each_entry(). For incomplete iteration, recently
introduced iteration wrappers are updated to use LIST macros.

21 files changed:
include/haproxy/proxy-t.h
include/haproxy/proxy.h
src/cache.c
src/cfgdiag.c
src/cfgparse.c
src/check.c
src/debug.c
src/fcgi-app.c
src/filters.c
src/haproxy.c
src/haterm.c
src/limits.c
src/log.c
src/mworker.c
src/proxy.c
src/resolvers.c
src/server.c
src/server_state.c
src/ssl_ckch.c
src/stats-proxy.c
src/stats.c

index a5a5190692e94d01f16e264e4fffcd995a2c5527..7ff9f442bec3c978bb7b68bd167ed9773dacc8af 100644 (file)
@@ -324,6 +324,7 @@ struct proxy {
 
        struct list global_list;                /* list member for global proxy list */
        struct list el;                         /* attach point in various list
+                                                * - <main_proxies> for non internal instance
                                                 * - <cfg_log_forward> for log forwarder
                                                 * - <sink_proxies_list> for sink
                                                 * - <defaults_list> for defaults section
index 2884e8110d15e47fc6eca59eecc1bc90e62eeee0..a1720566f8d789cf68a4238b1cc291828f3ed305 100644 (file)
@@ -35,7 +35,7 @@
 #include <haproxy/ticks.h>
 #include <haproxy/thread.h>
 
-extern struct proxy *proxies_list;
+extern struct list main_proxies;
 extern struct list proxies;
 extern struct ceb_root *used_proxy_id;  /* list of proxy IDs in use */
 extern unsigned int error_snapshot_id;  /* global ID assigned to each error then incremented */
@@ -320,14 +320,15 @@ static inline void increment_send_rate(uint64_t bytes, int splice)
  */
 static inline void main_proxies_register(struct proxy *px)
 {
-       px->next = proxies_list;
-       proxies_list = px;
+       LIST_INSERT(&main_proxies, &px->el);
 }
 
 /* Returns first entry in main proxies list or NULL if empty. */
 static inline struct proxy *main_proxies_first(void)
 {
-       return proxies_list;
+       if (LIST_ISEMPTY(&main_proxies))
+               return NULL;
+       return LIST_ELEM(main_proxies.n, struct proxy *, el);
 }
 
 /* Returns first entry in main proxies list unless <px> is already set. This is
@@ -335,15 +336,17 @@ static inline struct proxy *main_proxies_first(void)
  */
 static inline struct proxy *main_proxies_cond_first(struct proxy *px)
 {
-       if (!px)
-               px = proxies_list;
+       if (!px && !LIST_ISEMPTY(&main_proxies))
+               px = LIST_ELEM(main_proxies.n, struct proxy *, el);
        return px;
 }
 
 /* Return next entry after <px> in main proxies list or NULL if reaching end of list. */
 static inline struct proxy *main_proxies_next(const struct proxy *px)
 {
-       return px->next;
+       if (px->el.n == &main_proxies)
+               return NULL;
+       return LIST_ELEM(px->el.n, struct proxy *, el);
 }
 
 #endif /* _HAPROXY_PROXY_H */
index dbee7ae7afeac4a2d8b7c168a25ba425ab9562c3..b9fa2d45a91c3641b78440fbac2ff1ced142fccd 100644 (file)
@@ -3090,7 +3090,7 @@ int post_check_cache()
                /* Find all references for this cache in the existing filters
                 * (over all proxies) and reference it in matching filters.
                 */
-               for (px = proxies_list; px; px = px->next) {
+               list_for_each_entry(px, &main_proxies, el) {
                        struct flt_conf *fconf;
                        struct cache_flt_conf *cconf;
 
index f7ce45ac04316c2e266394b4d33b178d83265391..592120b3b6fb7e35bf5a2c9002e867cd8b98c427 100644 (file)
@@ -90,7 +90,7 @@ static void run_servers_diag(int *ret)
        struct proxy  *px;
        struct server *srv;
 
-       for (px = proxies_list; px; px = px->next) {
+       list_for_each_entry(px, &main_proxies, el) {
                for (srv = px->srv; srv; srv = srv->next) {
                        srv_diag_cookies(ret, srv, &cookies_tree);
                        srv_diag_check_reuse(ret, srv, px);
index 4c5c3a828b362edbbe272c26d57eeabce207d4b9..3a7a533fc9ad9ff54eafc8a3bbdb8cf2473cacf7 100644 (file)
@@ -2269,7 +2269,7 @@ static struct proxy *_get_next_proxy(void *head, struct proxy *cur)
        struct proxy *next;
        struct list *list = (struct list *)head;
 
-       if (head == &cfg_log_forward || head == &sink_proxies_list) {
+       if (head == &main_proxies || head == &cfg_log_forward || head == &sink_proxies_list) {
                next = cur ?
                  LIST_ELEM(cur->el.n, struct proxy *, el) :
                  LIST_ELEM(list->n,   struct proxy *, el);
@@ -2295,8 +2295,9 @@ static struct proxy *_get_next_proxy(void *head, struct proxy *cur)
  */
 int check_config_validity()
 {
+       struct list tmp_list = LIST_HEAD_INIT(tmp_list);
        int cfgerr = 0, ret;
-       struct proxy *defpx;
+       struct proxy *defpx, *old;
        void *init_proxies_list = NULL;
        struct stktable *t;
        struct server *newsrv = NULL;
@@ -2386,17 +2387,11 @@ int check_config_validity()
                goto out;
 
        /* first, we will invert the proxy list order */
-       curproxy = NULL;
-       while (proxies_list) {
-               struct proxy *next;
-
-               next = proxies_list->next;
-               proxies_list->next = curproxy;
-               curproxy = proxies_list;
-               if (!next)
-                       break;
-               proxies_list = next;
+       list_for_each_entry_safe(curproxy, old, &main_proxies, el) {
+               LIST_DELETE(&curproxy->el);
+               LIST_INSERT(&tmp_list, &curproxy->el);
        }
+       LIST_SPLICE(&main_proxies, &tmp_list);
 
        /*
         * we must finish to initialize certain things on the servers,
@@ -2438,7 +2433,7 @@ int check_config_validity()
 
        curproxy = NULL;
        /* starting to initialize the main proxies list */
-       init_proxies_list = proxies_list;
+       init_proxies_list = &main_proxies;
 
 init_proxies_list_stage1:
        while ((curproxy = _get_next_proxy(init_proxies_list, curproxy))) {
@@ -2497,7 +2492,7 @@ init_proxies_list_stage1:
         * We have just initialized the main proxies list
         * we must also configure the log-forward proxies list
         */
-       if (init_proxies_list == proxies_list) {
+       if (init_proxies_list == &main_proxies) {
                init_proxies_list = &cfg_log_forward;
                goto init_proxies_list_stage1;
        }
@@ -2540,7 +2535,7 @@ init_proxies_list_stage1:
 
        curproxy = NULL;
        /* starting to initialize the main proxies list */
-       init_proxies_list = proxies_list;
+       init_proxies_list = &main_proxies;
 
 init_proxies_list_stage2:
        while ((curproxy = _get_next_proxy(init_proxies_list, curproxy))) {
@@ -2650,7 +2645,7 @@ init_proxies_list_stage2:
         * We have just initialized the main proxies list
         * we must also configure the log-forward proxies list
         */
-       if (init_proxies_list == proxies_list) {
+       if (init_proxies_list == &main_proxies) {
                init_proxies_list = &cfg_log_forward;
                goto init_proxies_list_stage2;
        }
@@ -2664,7 +2659,7 @@ init_proxies_list_stage2:
         * Recount currently required checks.
         */
 
-       for (curproxy=proxies_list; curproxy; curproxy=curproxy->next) {
+       list_for_each_entry(curproxy, &main_proxies, el) {
                int optnum;
 
                for (optnum = 0; cfg_opts[optnum].name; optnum++)
@@ -2830,7 +2825,7 @@ init_proxies_list_stage2:
         * be done earlier because the data size may be discovered while parsing
         * other proxies.
         */
-       for (curproxy = proxies_list; curproxy; curproxy = curproxy->next) {
+       list_for_each_entry(curproxy, &main_proxies, el) {
                if ((curproxy->flags & PR_FL_DISABLED) || !curproxy->table)
                        continue;
 
@@ -2880,7 +2875,7 @@ init_proxies_list_stage2:
 
        /* Update server_state_file_name to backend name if backend is supposed to use
         * a server-state file locally defined and none has been provided */
-       for (curproxy = proxies_list; curproxy; curproxy = curproxy->next) {
+       list_for_each_entry(curproxy, &main_proxies, el) {
                if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
                    curproxy->server_state_file_name == NULL)
                        curproxy->server_state_file_name = strdup(curproxy->id);
index 3cd9a835de618b8b62aec2666574ae212f7aa24d..3a5442094cef45bba84e7c3df53b1ce9563fae37 100644 (file)
@@ -1697,7 +1697,7 @@ static int start_checks()
         * a shorter interval will start independently and will not dictate
         * too short an interval for all others.
         */
-       for (px = proxies_list; px; px = px->next) {
+       list_for_each_entry(px, &main_proxies, el) {
                for (s = px->srv; s; s = s->next) {
                        if ((px->options2 & PR_O2_USE_SBUF_CHECK) &&
                            (s->check.tcpcheck->rs && s->check.tcpcheck->rs->flags & TCPCHK_RULES_MAY_USE_SBUF))
@@ -1729,7 +1729,7 @@ static int start_checks()
         * by the number of servers, weighted by the server's position in the
         * list.
         */
-       for (px = proxies_list; px; px = px->next) {
+       list_for_each_entry(px, &main_proxies, el) {
                if ((px->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
                        if (init_pid_list()) {
                                ha_alert("Starting [%s] check: out of memory.\n", px->id);
index e5c90580a8823d9f74755daa506cde99a2809fdc..47c70437a428a50ffbd88a1db93b516854b59240 100644 (file)
@@ -153,7 +153,7 @@ struct post_mortem {
        struct tgroup_ctx  *tgroup_ctx;  // pointer to ha_tgroup_ctx
        struct thread_ctx  *thread_ctx;  // pointer to ha_thread_ctx
        struct list *pools;              // pointer to the head of the pools list
-       struct proxy **proxies;          // pointer to the head of the proxies list
+       struct list *proxies;            // pointer to the head of the proxies list
        struct global *global;           // pointer to the struct global
        struct fdtab **fdtab;            // pointer to the fdtab array
        struct activity *activity;       // pointer to the activity[] per-thread array
@@ -2920,7 +2920,7 @@ process_info:
        post_mortem.tgroup_ctx  = ha_tgroup_ctx;
        post_mortem.thread_ctx  = ha_thread_ctx;
        post_mortem.pools = &pools;
-       post_mortem.proxies = &proxies_list;
+       post_mortem.proxies = &main_proxies;
        post_mortem.global = &global;
        post_mortem.fdtab = &fdtab;
        post_mortem.activity = activity;
index 688f2ada621db961cc56419950c0f875e3ac0889..49f87a70fb58e9ed1d89ff3ed313b5951c6bd163 100644 (file)
@@ -626,7 +626,7 @@ static int cfg_fcgi_apps_postparser()
        struct server *srv;
        int err_code = 0;
 
-       for (px = proxies_list; px; px = px->next) {
+       list_for_each_entry(px, &main_proxies, el) {
                struct fcgi_flt_conf *fcgi_conf = find_px_fcgi_conf(px);
                int nb_fcgi_srv = 0;
 
index 944b534e91d20625a0502aa4d088a8ec3ac79303..b9edfe5f50a940d1c022a3ad768e2af8ee35f5a0 100644 (file)
@@ -468,7 +468,7 @@ flt_init_all()
        struct proxy *px;
        int err_code = ERR_NONE;
 
-       for (px = proxies_list; px; px = px->next) {
+       list_for_each_entry(px, &main_proxies, el) {
                if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
                        continue;
 
@@ -490,7 +490,7 @@ flt_init_all_per_thread()
        struct proxy *px;
        int err_code = 0;
 
-       for (px = proxies_list; px; px = px->next) {
+       list_for_each_entry(px, &main_proxies, el) {
                if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
                        continue;
 
@@ -573,7 +573,7 @@ flt_deinit_all_per_thread()
 {
        struct proxy *px;
 
-       for (px = proxies_list; px; px = px->next)
+       list_for_each_entry(px, &main_proxies, el)
                flt_deinit_per_thread(px);
 }
 
index 774c6bca539aa56d9861f02e3cfb24e18db7d53b..69d5414ea17777559277a8d841cb1c02a2560073 100644 (file)
@@ -904,10 +904,10 @@ static void sig_listen(struct sig_handler *sh)
  */
 static void sig_dump_state(struct sig_handler *sh)
 {
-       struct proxy *p = proxies_list;
+       struct proxy *p;
 
        ha_warning("SIGHUP received, dumping servers states.\n");
-       while (p) {
+       list_for_each_entry(p, &main_proxies, el) {
                struct server *s = p->srv;
 
                send_log(p, LOG_NOTICE, "SIGHUP received, dumping servers states for proxy %s.\n", p->id);
@@ -943,8 +943,6 @@ static void sig_dump_state(struct sig_handler *sh)
                }
                ha_warning("%s\n", trash.area);
                send_log(p, LOG_NOTICE, "%s\n", trash.area);
-
-               p = p->next;
        }
 }
 
@@ -2314,7 +2312,7 @@ static void step_init_2(int argc, char** argv)
        /* Preload internal counters. */
        apply_stats_file();
 
-       for (px = proxies_list; px; px = px->next)
+       list_for_each_entry(px, &main_proxies, el)
                srv_compute_all_admin_states(px);
 
        /* Apply servers' configured address */
@@ -2367,9 +2365,10 @@ static void step_init_2(int argc, char** argv)
                        if (pr->peers_fe)
                                break;
 
-               for (px = proxies_list; px; px = px->next)
+               list_for_each_entry(px, &main_proxies, el) {
                        if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
                                break;
+               }
 
                if (!px) {
                        /* We may only have log-forward section */
@@ -2522,7 +2521,7 @@ static void step_init_2(int argc, char** argv)
                global.node = strdup(hostname);
 
        /* stop disabled proxies */
-       for (px = proxies_list; px; px = px->next) {
+       list_for_each_entry(px, &main_proxies, el) {
                if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
                        stop_proxy(px);
        }
@@ -2798,7 +2797,7 @@ static void read_cfg_in_discovery_mode(int argc, char **argv)
 
 void deinit(void)
 {
-       struct proxy *p = proxies_list, *p0;
+       struct proxy *p, *p0;
        struct cfgfile *cfg, *cfg_tmp;
        struct logger *log, *logb;
        struct build_opts_str *bol, *bolb;
@@ -2853,11 +2852,8 @@ void deinit(void)
        }
 
        deinit_signals();
-       while (p) {
-               p0 = p;
-               p = p->next;
-               proxy_drop(p0);
-       }/* end while(p) */
+       list_for_each_entry_safe(p, p0, &main_proxies, el)
+               proxy_drop(p);
 
        /* we don't need to free sink_proxies_list nor cfg_log_forward proxies since
         * they are respectively cleaned up in sink_deinit() and deinit_log_forward()
index 5ee2848522bef4407478ca9e3ef33794f23d5333..cc3a9b2d903db2c6e4bafc36e8b509a286cd817f 100644 (file)
@@ -1234,7 +1234,7 @@ static void hstream_init_splicing(void)
        if (!(global.tune.options & GTUNE_USE_SPLICE) || !global.maxpipes)
                return;
 
-       for (px = proxies_list; px; px = px->next) {
+       list_for_each_entry(px, &main_proxies, el) {
                if ((px->cap & PR_CAP_FE) && !(px->flags & PR_FL_DISABLED) && px->stream_new_from_sc == hstream_new) {
                        haterm_used = 1;
                        break;
index fcd92975244c3f853544f73e0d327242f462c4ac..236c1ea8f26bf29e3ced107719dafad4bffe6671 100644 (file)
@@ -71,7 +71,7 @@ int compute_ideal_maxpipes()
        int pipes;
        int max;
 
-       for (cur = proxies_list; cur; cur = cur->next) {
+       list_for_each_entry(cur, &main_proxies, el) {
                if (cur->options2 & (PR_O2_SPLIC_ANY)) {
                        if (cur->cap & PR_CAP_FE) {
                                max = cur->maxconn;
index eb02b8bee333f8550d613ca2578b02ddc68a571c..bd3a03aa98b8ec466aadc1fbe8f56d405373a2a5 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -6905,7 +6905,7 @@ static int postresolve_loggers()
        /* global log directives */
        err_code |= postresolve_logger_list(NULL, &global.loggers, NULL, NULL);
        /* proxy log directives */
-       for (px = proxies_list; px; px = px->next)
+       list_for_each_entry(px, &main_proxies, el)
                err_code |= postresolve_logger_list(px, &px->loggers, "proxy", px->id);
        /* log-forward log directives */
        list_for_each_entry(px, &cfg_log_forward, el)
index eee44c09612fdbef1d5e2ce92379f80469dd4fef..28028bc5704a2fef1131b1d690fa66a685fc25ef 100644 (file)
@@ -600,7 +600,7 @@ restart_wait:
                        mworker_on_new_child_failure(exitpid, status);
 
                        /* Detach all listeners */
-                       for (curproxy = proxies_list; curproxy; curproxy = curproxy->next) {
+                       list_for_each_entry(curproxy, &main_proxies, el) {
                                list_for_each_entry_safe(l, l_next, &curproxy->conf.listeners, by_fe) {
                                        if ((l->rx.fd == child->ipc_fd[0]) || (l->rx.fd == child->ipc_fd[1])) {
                                                unbind_listener(l);
@@ -781,7 +781,7 @@ void mworker_cleanlisteners()
        }
 
        /* main proxies cleanup */
-       for (curproxy = proxies_list; curproxy; curproxy = curproxy->next) {
+       list_for_each_entry(curproxy, &main_proxies, el) {
                int listen_in_master = 0;
 
                list_for_each_entry_safe(l, l_next, &curproxy->conf.listeners, by_fe) {
index 23adbbf0e74c47f382b7f7a753c54b69c6727322..eaab91f6f5a42ea206e012a8005c46f05bf14492 100644 (file)
 __decl_spinlock(proxies_del_lock);
 
 int listeners; /* # of proxy listeners, set by cfgparse */
-struct proxy *proxies_list  = NULL;     /* list of main proxies */
-struct list proxies = LIST_HEAD_INIT(proxies); /* list of all proxies */
+
+/* List of non-default and non-internal proxies, except mworker and cli_fe which are stored in it.
+ * Used for check_config_validity() post init and most runtime operations (stats, ...).
+ */
+struct list main_proxies = LIST_HEAD_INIT(main_proxies);
+
+/* List of all proxies, except defaults.
+ * Currently only used for post_proxy_check_fct and post_server_check_fct post init.
+ */
+struct list proxies = LIST_HEAD_INIT(proxies);
+
 struct ceb_root *used_proxy_id = NULL; /* list of proxy IDs in use */
 struct ceb_root *proxy_by_name = NULL; /* tree of proxies sorted by name */
 struct ceb_root *defproxy_by_name = NULL; /* tree of default proxies sorted by name (dups possible) */
@@ -3864,15 +3873,13 @@ struct task *hard_stop(struct task *t, void *context, unsigned int state)
 
        ha_warning("soft-stop running for too long, performing a hard-stop.\n");
        send_log(NULL, LOG_WARNING, "soft-stop running for too long, performing a hard-stop.\n");
-       p = proxies_list;
-       while (p) {
+       list_for_each_entry(p, &main_proxies, el) {
                if ((p->cap & PR_CAP_FE) && (p->feconn > 0)) {
                        ha_warning("Proxy %s hard-stopped (%d remaining conns will be closed).\n",
                                   p->id, p->feconn);
                        send_log(p, LOG_WARNING, "Proxy %s hard-stopped (%d remaining conns will be closed).\n",
                                p->id, p->feconn);
                }
-               p = p->next;
        }
 
        thread_isolate();
@@ -3924,12 +3931,10 @@ static void do_soft_stop_now()
        thread_release();
 
        /* Loop on proxies to stop backends */
-       p = proxies_list;
-       while (p) {
+       list_for_each_entry(p, &main_proxies, el) {
                HA_RWLOCK_WRLOCK(PROXY_LOCK, &p->lock);
                proxy_cond_disable(p);
                HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &p->lock);
-               p = p->next;
        }
 
        /* signal zero is used to broadcast the "stopping" event */
@@ -4271,7 +4276,7 @@ void proxy_adjust_all_maxconn()
        struct proxy *curproxy;
        struct switching_rule *swrule1, *swrule2;
 
-       for (curproxy = proxies_list; curproxy; curproxy = curproxy->next) {
+       list_for_each_entry(curproxy, &main_proxies, el) {
                if (curproxy->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
                        continue;
 
@@ -4315,7 +4320,7 @@ void proxy_adjust_all_maxconn()
        /* automatically compute fullconn if not set. We must not do it in the
         * loop above because cross-references are not yet fully resolved.
         */
-       for (curproxy = proxies_list; curproxy; curproxy = curproxy->next) {
+       list_for_each_entry(curproxy, &main_proxies, el) {
                if (curproxy->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
                        continue;
 
@@ -4837,7 +4842,7 @@ static int cli_parse_shutdown_frontend(char **args, char *payload, struct appctx
  */
 static int cli_parse_add_backend(char **args, char *payload, struct appctx *appctx, void *private)
 {
-       struct proxy *px, *defpx, *next;
+       struct proxy *px, *defpx;
        struct post_proxy_check_fct *ppcf;
        const char *be_name, *def_name, *guid = NULL, *err;
        char *msg = NULL;
@@ -4972,15 +4977,7 @@ static int cli_parse_add_backend(char **args, char *payload, struct appctx *appc
        proxy_index_id(px);
        dynpx_next_id = px->uuid;
 
-       if (!proxies_list) {
-               proxies_list = px;
-       }
-       else {
-               for (next = proxies_list; next->next; next = next->next)
-                       ;
-               next->next = px;
-       }
-       px->next = NULL;
+       LIST_APPEND(&main_proxies, &px->el);
 
        thread_release();
 
@@ -5087,7 +5084,7 @@ int be_check_for_deletion(const char *bename, struct proxy **pb, const char **pm
 static int cli_parse_delete_backend(char **args, char *payload, struct appctx *appctx, void *private)
 {
        struct watcher *px_watch;
-       struct proxy *px, *prev;
+       struct proxy *px;
        const char *msg;
        char *be_name;
        int ret;
@@ -5117,16 +5114,8 @@ static int cli_parse_delete_backend(char **args, char *payload, struct appctx *a
        ceb32_item_delete(&used_proxy_id, conf.uuid_node, uuid, px);
        cebis_item_delete(&proxy_by_name, conf.name_node, id, px);
 
-       /* Detach backend from global proxies_list. */
-       if (proxies_list == px) {
-               proxies_list = px->next;
-       }
-       else {
-               for (prev = proxies_list->next; prev && prev->next != px; prev = prev->next)
-                       ;
-               BUG_ON(!prev); /* Proxy instance not found in global list ? */
-               prev->next = px->next;
-       }
+       /* Detach backend from global main_proxies. */
+       LIST_DELETE(&px->el);
 
        px->flags |= PR_FL_DELETED;
 
index 89dc104a03927d7e8a7742e2ac39314780eaf6b1..2144561dce041a8e78628dd647c370ec8a6abea5 100644 (file)
@@ -2808,7 +2808,7 @@ static int resolvers_finalize_config(void)
                task_wakeup(t, TASK_WOKEN_INIT);
        }
 
-       for (px = proxies_list; px; px = px->next) {
+       list_for_each_entry(px, &main_proxies, el) {
                struct server *srv;
 
                if (px->flags & PR_FL_DISABLED) {
index 4bdcb8be00484be25c2a8cd17e1af53def74dabd..8248c6cc461e1ba271ebd4cbc7c5a687f4e68d6b 100644 (file)
@@ -5462,13 +5462,12 @@ int srv_init_addr(void)
        struct proxy *curproxy;
        int return_code = 0;
 
-       curproxy = proxies_list;
-       while (curproxy) {
+       list_for_each_entry(curproxy, &main_proxies, el) {
                struct server *srv;
 
                /* servers are in backend only */
                if (!(curproxy->cap & PR_CAP_BE) || (curproxy->flags & (PR_FL_DISABLED|PR_FL_STOPPED)))
-                       goto srv_init_addr_next;
+                       continue;
 
                for (srv = curproxy->srv; srv; srv = srv->next) {
                        set_usermsgs_ctx(srv->conf.file, srv->conf.line, &srv->obj_type);
@@ -5476,9 +5475,6 @@ int srv_init_addr(void)
                                return_code |= srv_iterate_initaddr(srv);
                        reset_usermsgs_ctx();
                }
-
- srv_init_addr_next:
-               curproxy = curproxy->next;
        }
 
        return return_code;
index 3b728281a5b37dcb2b3c415b6fad6c8b6ea69448..426cad95609d02014e8673458c92b6e0b14bf855 100644 (file)
@@ -833,7 +833,7 @@ void apply_server_state(void)
 
   no_globalfile:
        /* parse all proxies and load states form tree (global file) or from local file */
-       for (curproxy = proxies_list; curproxy != NULL; curproxy = curproxy->next) {
+       list_for_each_entry(curproxy, &main_proxies, el) {
                struct eb_root local_state_tree = EB_ROOT_UNIQUE;
 
                /* Must be an enabled backend with at least a server */
index 59fb01456a1586e64d4eb907eb423975513d8635..3c4c9d8e7f39e9b42b1577f3d38a24743b0a9d43 100644 (file)
@@ -1863,7 +1863,7 @@ static int cli_parse_show_sni(char **args, char *payload, struct appctx *appctx,
                        if (*args[cur_arg+1] == '\0')
                                return cli_err(appctx, "'-f' requires a frontend name!\n");
 
-                       for (px = proxies_list; px; px = px->next) {
+                       list_for_each_entry(px, &main_proxies, el) {
 
                                /* only check the frontends */
                                if (!(px->cap & PR_CAP_FE))
index 5b43aac574062012c55604d93dbebc6dbd39dd43..dbcfdb9df90dbbe335a1942ddf074030a4fd4dbf 100644 (file)
@@ -1667,7 +1667,7 @@ void proxy_stats_clear_counters(int clrall, struct list *stat_modules)
        struct listener *li;
        struct stats_module *mod;
 
-       for (px = proxies_list; px; px = px->next) {
+       list_for_each_entry(px, &main_proxies, el) {
                if (clrall) {
                        memset(&px->be_counters, 0, sizeof(px->be_counters));
                        memset(&px->fe_counters, 0, sizeof(px->fe_counters));
@@ -1715,7 +1715,7 @@ void proxy_stats_clear_counters(int clrall, struct list *stat_modules)
                if (!mod->clearable && !clrall)
                        continue;
 
-               for (px = proxies_list; px; px = px->next) {
+               list_for_each_entry(px, &main_proxies, el) {
                        enum stats_domain_px_cap mod_cap = stats_px_get_cap(mod->domain_flags);
 
                        if (px->cap & PR_CAP_FE && mod_cap & STATS_PX_CAP_FE) {
index 442632ad48e12eedadc1af5ceb516b8c40283789..cf0d89e00256f943275bdd3a8fab657e17583aa2 100644 (file)
@@ -1226,7 +1226,7 @@ static int allocate_stats_px_postcheck(void)
                i += offset;
        }
 
-       for (px = proxies_list; px; px = px->next) {
+       list_for_each_entry(px, &main_proxies, el) {
                if (!stats_allocate_proxy_counters(px)) {
                        ha_alert("stats: cannot allocate all counters for proxy statistics\n");
                        err_code |= ERR_ALERT | ERR_FATAL;