]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: counters: add a dedicated storage for extra_counters in various structs
authorWilly Tarreau <w@1wt.eu>
Tue, 24 Feb 2026 19:08:49 +0000 (20:08 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 26 Feb 2026 16:03:47 +0000 (17:03 +0100)
Servers, proxies, listeners and resolvers all use extra_counters. We'll
need to move the storage to per-tgroup for those where it matters. Now
we're relying on an external storage, and the data member of the struct
was replaced with a pointer to that pointer to data called datap. When
the counters are registered, these datap are set to point to relevant
locations. In the case of proxies and servers, it points to the first
tgrp's storage. For listeners and resolvers, it points to a local
storage. The rationale here is that listeners are limited to a single
group anyway, and that resolvers have a low enough load so that we do
not care about contention there.

Nothing should change for the user at this point.

include/haproxy/counters-t.h
include/haproxy/counters.h
include/haproxy/dns-t.h
include/haproxy/listener-t.h
include/haproxy/proxy-t.h
include/haproxy/server-t.h
include/haproxy/stats.h
src/proxy.c
src/resolvers.c
src/server.c
src/stats.c

index 8c21d9b7088cc361852e1e590bb1865f174e7a6c..9a45609e2740c0df428518030e6c8ba912ab32a0 100644 (file)
@@ -197,7 +197,7 @@ enum counters_type {
 };
 
 struct extra_counters {
-       char *data; /* heap containing counters allocated in a linear fashion */
+       char **datap; /* points to pointer to heap containing counters allocated in a linear fashion */
        size_t size; /* size of allocated data */
        enum counters_type type; /* type of object containing the counters */
 };
index a9e6c30ea06e7cd315fcc85c40dbfebd6c7402da..f40dd6d844aabd2290b5c3bfbafc8cedc02b4335 100644 (file)
@@ -106,16 +106,17 @@ void counters_be_shared_drop(struct be_counters_shared *counters);
 /* Manipulation of extra_counters, for boot-time registrable modules */
 #define EXTRA_COUNTERS_GET(counters, mod) \
        (likely(counters) ? \
-               ((void *)((counters)->data + (mod)->counters_off[(counters)->type])) : \
+               ((void *)(*(counters)->datap + (mod)->counters_off[(counters)->type])) : \
                (trash_counters))
 
-#define EXTRA_COUNTERS_REGISTER(counters, ctype, alloc_failed_label) \
+#define EXTRA_COUNTERS_REGISTER(counters, ctype, alloc_failed_label, storage)  \
        do {                                                         \
                typeof(*counters) _ctr;                              \
                _ctr = calloc(1, sizeof(*_ctr));                     \
                if (!_ctr)                                           \
                        goto alloc_failed_label;                     \
                _ctr->type = (ctype);                                \
+               _ctr->datap = (storage);                             \
                *(counters) = _ctr;                                  \
        } while (0)
 
@@ -129,22 +130,22 @@ void counters_be_shared_drop(struct be_counters_shared *counters);
 #define EXTRA_COUNTERS_ALLOC(counters, alloc_failed_label) \
        do {                                               \
                typeof(counters) _ctr = (counters);        \
-               _ctr->data = malloc((_ctr)->size);         \
-               if (!_ctr->data)                           \
+               *_ctr->datap = malloc((_ctr)->size);       \
+               if (!*_ctr->datap)                         \
                        goto alloc_failed_label;           \
        } while (0)
 
 #define EXTRA_COUNTERS_INIT(counters, mod, init_counters, init_counters_size) \
        do {                                                                  \
                typeof(counters) _ctr = (counters);                           \
-               memcpy(_ctr->data + mod->counters_off[_ctr->type],            \
+               memcpy(*_ctr->datap + mod->counters_off[_ctr->type],          \
                       (init_counters), (init_counters_size));                \
        } while (0)
 
 #define EXTRA_COUNTERS_FREE(counters)           \
        do {                                    \
                if (counters) {                 \
-                       free((counters)->data); \
+                       ha_free((counters)->datap);\
                        free(counters);         \
                }                               \
        } while (0)
index 344b085d99fbfa546380f13e8ea6b63e410e6e59..10175cfdf0ae2423a1056c201e08a85d532b997b 100644 (file)
@@ -152,6 +152,7 @@ struct dns_nameserver {
        struct dns_stream_server *stream; /* used for tcp dns */
 
        EXTRA_COUNTERS(extra_counters);
+       char *extra_counters_storage;    /* storage used for extra_counters above */
        struct dns_counters *counters;
 
        struct list list;               /* nameserver chained list */
index cc08a224351a3efa3910aef4a40af78b4a6b1155..a6990cbd9b66daf24c4795e3cd1ba47c1c6ce052 100644 (file)
@@ -263,6 +263,7 @@ struct listener {
 
        struct li_per_thread *per_thr;  /* per-thread fields (one per thread in the group) */
 
+       char *extra_counters_storage;   /* storage for extra_counters */
        EXTRA_COUNTERS(extra_counters);
 };
 
index c71bde5264e16b42eafee90263d730dcadd5df26..18b25ce81223c7f7054c81bb2ae7b9555d84443c 100644 (file)
@@ -305,6 +305,8 @@ struct error_snapshot {
 struct proxy_per_tgroup {
        struct queue queue;
        struct lbprm_per_tgrp lbprm;
+       char *extra_counters_fe_storage;        /* storage for extra_counters_fe */
+       char *extra_counters_be_storage;        /* storage for extra_counters_be */
 } THREAD_ALIGNED();
 
 struct proxy {
index 325361767ee28a99bec8b8fb7ee24a321e838b80..c8f318c5ce541def2c3414c91890989c8687b29e 100644 (file)
@@ -286,6 +286,7 @@ struct srv_per_tgroup {
        struct queue queue;                     /* pending connections */
        struct server *server;                  /* pointer to the corresponding server */
        struct eb32_node lb_node;               /* node used for tree-based load balancing */
+       char *extra_counters_storage;           /* storage for extra_counters */
        struct server *next_full;               /* next server in the temporary full list */
        unsigned int last_other_tgrp_served;    /* Last other tgrp we dequeued from */
        unsigned int self_served;               /* Number of connection we dequeued from our own queue */
index acebd27b89cf0f6ea6f8bf07bbbc3d8f9971fa31..a02bcb6dd6a46d75b6a3d40a87a97cbed35f48e6 100644 (file)
@@ -168,7 +168,7 @@ static inline enum stats_domain_px_cap stats_px_get_cap(uint32_t domain)
 }
 
 int stats_allocate_proxy_counters_internal(struct extra_counters **counters,
-                                           int type, int px_cap);
+                                           int type, int px_cap, char **storage);
 int stats_allocate_proxy_counters(struct proxy *px);
 
 void stats_register_module(struct stats_module *m);
index 49aa4a2ec9f202fb6f8ba1ee890f4196c6e15430..ed6a92c1cc434151da564067cd86f1ab39160e63 100644 (file)
@@ -4914,7 +4914,8 @@ static int cli_parse_add_backend(char **args, char *payload, struct appctx *appc
 
        if (!stats_allocate_proxy_counters_internal(&px->extra_counters_be,
                                                    COUNTERS_BE,
-                                                   STATS_PX_CAP_BE)) {
+                                                   STATS_PX_CAP_BE,
+                                                   &px->per_tgrp->extra_counters_be_storage)) {
                memprintf(&msg, "failed to allocate extra counters");
                goto err;
        }
index 6cbb4448acb1599dd21e18c2f8c85784b2af5b19..4a62427ac68dc89c85793ff872b0179e0deef99f 100644 (file)
@@ -2906,7 +2906,7 @@ int resolv_allocate_counters(struct list *stat_modules)
        list_for_each_entry(resolvers, &sec_resolvers, list) {
                list_for_each_entry(ns, &resolvers->nameservers, list) {
                        EXTRA_COUNTERS_REGISTER(&ns->extra_counters, COUNTERS_RSLV,
-                                               alloc_failed);
+                                               alloc_failed, &ns->extra_counters_storage);
 
                        list_for_each_entry(mod, stat_modules, list) {
                                EXTRA_COUNTERS_ADD(mod,
@@ -2918,12 +2918,12 @@ int resolv_allocate_counters(struct list *stat_modules)
                        EXTRA_COUNTERS_ALLOC(ns->extra_counters, alloc_failed);
 
                        list_for_each_entry(mod, stat_modules, list) {
-                               memcpy(ns->extra_counters->data + mod->counters_off[ns->extra_counters->type],
+                               memcpy(*ns->extra_counters->datap + mod->counters_off[ns->extra_counters->type],
                                       mod->counters, mod->counters_size);
 
                                /* Store the ns counters pointer */
                                if (strcmp(mod->name, "resolvers") == 0) {
-                                       ns->counters = (struct dns_counters *)ns->extra_counters->data + mod->counters_off[COUNTERS_RSLV];
+                                       ns->counters = (struct dns_counters *)(*ns->extra_counters->datap) + mod->counters_off[COUNTERS_RSLV];
                                        ns->counters->id = ns->id;
                                        ns->counters->ns_puid = ns->puid;
                                        ns->counters->pid = resolvers->id;
index 10de4faa325091c528ea07c9ae13a60803dec27a..536f96a36419746eb63289ca41b8ce0576bfc045 100644 (file)
@@ -6285,7 +6285,8 @@ static int cli_parse_add_server(char **args, char *payload, struct appctx *appct
 
        if (!stats_allocate_proxy_counters_internal(&srv->extra_counters,
                                                    COUNTERS_SV,
-                                                   STATS_PX_CAP_SRV)) {
+                                                   STATS_PX_CAP_SRV,
+                                                   &srv->per_tgrp->extra_counters_storage)) {
                ha_alert("failed to allocate extra counters for server.\n");
                goto out;
        }
index ad2a11d83452aca1d7d84ccca0503fbc4c85f7ba..c8347bf676608115aacd294ac88a13aef5bdde17 100644 (file)
@@ -1094,11 +1094,11 @@ static void cli_io_handler_release_dump_stat_file(struct appctx *appctx)
 }
 
 int stats_allocate_proxy_counters_internal(struct extra_counters **counters,
-                                           int type, int px_cap)
+                                           int type, int px_cap, char **storage)
 {
        struct stats_module *mod;
 
-       EXTRA_COUNTERS_REGISTER(counters, type, alloc_failed);
+       EXTRA_COUNTERS_REGISTER(counters, type, alloc_failed, storage);
 
        list_for_each_entry(mod, &stats_module_list[STATS_DOMAIN_PROXY], list) {
                if (!(stats_px_get_cap(mod->domain_flags) & px_cap))
@@ -1133,7 +1133,8 @@ int stats_allocate_proxy_counters(struct proxy *px)
        if (px->cap & PR_CAP_FE) {
                if (!stats_allocate_proxy_counters_internal(&px->extra_counters_fe,
                                                            COUNTERS_FE,
-                                                           STATS_PX_CAP_FE)) {
+                                                           STATS_PX_CAP_FE,
+                                                           &px->per_tgrp->extra_counters_fe_storage)) {
                        return 0;
                }
        }
@@ -1141,7 +1142,8 @@ int stats_allocate_proxy_counters(struct proxy *px)
        if (px->cap & PR_CAP_BE) {
                if (!stats_allocate_proxy_counters_internal(&px->extra_counters_be,
                                                            COUNTERS_BE,
-                                                           STATS_PX_CAP_BE)) {
+                                                           STATS_PX_CAP_BE,
+                                                           &px->per_tgrp->extra_counters_be_storage)) {
                        return 0;
                }
        }
@@ -1149,7 +1151,8 @@ int stats_allocate_proxy_counters(struct proxy *px)
        for (sv = px->srv; sv; sv = sv->next) {
                if (!stats_allocate_proxy_counters_internal(&sv->extra_counters,
                                                            COUNTERS_SV,
-                                                           STATS_PX_CAP_SRV)) {
+                                                           STATS_PX_CAP_SRV,
+                                                           &sv->per_tgrp->extra_counters_storage)) {
                        return 0;
                }
        }
@@ -1157,7 +1160,8 @@ int stats_allocate_proxy_counters(struct proxy *px)
        list_for_each_entry(li, &px->conf.listeners, by_fe) {
                if (!stats_allocate_proxy_counters_internal(&li->extra_counters,
                                                            COUNTERS_LI,
-                                                           STATS_PX_CAP_LI)) {
+                                                           STATS_PX_CAP_LI,
+                                                           &li->extra_counters_storage)) {
                        return 0;
                }
        }