From: Willy Tarreau Date: Thu, 10 Jul 2025 14:16:24 +0000 (+0200) Subject: MEDIUM: proxy: take the defsrv out of the struct proxy X-Git-Tag: v3.3-dev4~86 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4ac28f07d0b2b6b0f970af8b5902ee48295ccb75;p=thirdparty%2Fhaproxy.git MEDIUM: proxy: take the defsrv out of the struct proxy The server struct has gone huge over time (~3.8kB), and having a copy of it in the defsrv section of the struct proxy costs a lot of RAM, that is not needed anymore at run time. This patch replaces this struct with a dynamically allocated one. The field is allocated and initialized during alloc_new_proxy() and is freed when the proxy is destroyed for now. But the goal will be to support freeing it after parsing the section. --- diff --git a/include/haproxy/proxy-t.h b/include/haproxy/proxy-t.h index 2d08a7852..2d4971012 100644 --- a/include/haproxy/proxy-t.h +++ b/include/haproxy/proxy-t.h @@ -352,7 +352,7 @@ struct proxy { #ifdef USE_QUIC struct list quic_init_rules; /* quic-initial rules */ #endif - struct server *srv, defsrv; /* known servers; default server configuration */ + struct server *srv, *defsrv; /* known servers; default server configuration */ struct lbprm lbprm; /* load-balancing parameters */ int srv_act, srv_bck; /* # of servers eligible for LB (UP|!checked) AND (enabled+weight!=0) */ int served; /* # of active sessions currently being served */ diff --git a/src/http_client.c b/src/http_client.c index cffc5de7e..8381e0434 100644 --- a/src/http_client.c +++ b/src/http_client.c @@ -1145,7 +1145,7 @@ struct proxy *httpclient_create_proxy(const char *id) goto err; } - srv_settings_cpy(srv_raw, &px->defsrv, 0); + srv_settings_cpy(srv_raw, px->defsrv, 0); srv_raw->iweight = 0; srv_raw->uweight = 0; srv_raw->xprt = xprt_get(XPRT_RAW); @@ -1165,7 +1165,7 @@ struct proxy *httpclient_create_proxy(const char *id) err_code |= ERR_ALERT | ERR_FATAL; goto err; } - srv_settings_cpy(srv_ssl, &px->defsrv, 0); + srv_settings_cpy(srv_ssl, px->defsrv, 0); srv_ssl->iweight = 0; srv_ssl->uweight = 0; srv_ssl->xprt = xprt_get(XPRT_SSL); diff --git a/src/proxy.c b/src/proxy.c index 24939662f..deef09b02 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -386,7 +386,10 @@ void deinit_proxy(struct proxy *p) /* also free default-server parameters since some of them might have * been dynamically allocated (e.g.: config hints, cookies, ssl..) */ - srv_free_params(&p->defsrv); + if (p->defsrv) { + srv_free_params(p->defsrv); + ha_free(&p->defsrv); + } if (p->lbprm.proxy_deinit) p->lbprm.proxy_deinit(p); @@ -1477,7 +1480,6 @@ void init_new_proxy(struct proxy *p) MT_LIST_INIT(&p->lbprm.lb_free_list); - p->defsrv.id = "default-server"; p->conf.used_listener_id = EB_ROOT; p->conf.used_server_id = EB_ROOT; p->used_server_addr = EB_ROOT_UNIQUE; @@ -1531,8 +1533,6 @@ void proxy_preset_defaults(struct proxy *defproxy) defproxy->options2 |= PR_O2_INDEPSTR; defproxy->max_out_conns = MAX_SRV_LIST; - srv_settings_init(&defproxy->defsrv); - lf_expr_init(&defproxy->logformat); lf_expr_init(&defproxy->logformat_sd); lf_expr_init(&defproxy->format_unique_id); @@ -1557,8 +1557,9 @@ void proxy_free_defaults(struct proxy *defproxy) proxy_free_common(defproxy); /* default proxy specific cleanup */ - ha_free((char **)&defproxy->defsrv.conf.file); + ha_free((char **)&defproxy->defsrv->conf.file); ha_free(&defproxy->defbe.name); + ha_free(&defproxy->defsrv); h = defproxy->req_cap; while (h) { @@ -1683,6 +1684,16 @@ int setup_new_proxy(struct proxy *px, const char *name, unsigned int cap, char * { init_new_proxy(px); + /* allocate the default server section */ + px->defsrv = calloc(1, sizeof(*px->defsrv)); + if (!px->defsrv) { + memprintf(errmsg, "out of memory"); + goto fail; + } + + px->defsrv->id = "default-server"; + srv_settings_init(px->defsrv); + if (name) { px->id = strdup(name); if (!px->id) { @@ -1706,6 +1717,7 @@ int setup_new_proxy(struct proxy *px, const char *name, unsigned int cap, char * if (name) memprintf(errmsg, "proxy '%s': %s", name, *errmsg); + ha_free(&px->defsrv); ha_free(&px->id); counters_fe_shared_drop(px->fe_counters.shared); counters_be_shared_drop(px->be_counters.shared); @@ -1736,6 +1748,8 @@ struct proxy *alloc_new_proxy(const char *name, unsigned int cap, char **errmsg) * but its not worth trying to unroll everything here just before * quitting. */ + if (curproxy) + free(curproxy->defsrv); free(curproxy); return NULL; } @@ -1792,7 +1806,7 @@ static int proxy_defproxy_cpy(struct proxy *curproxy, const struct proxy *defpro struct eb32_node *node; /* set default values from the specified default proxy */ - srv_settings_cpy(&curproxy->defsrv, &defproxy->defsrv, 0); + srv_settings_cpy(curproxy->defsrv, defproxy->defsrv, 0); curproxy->flags = (defproxy->flags & PR_FL_DISABLED); /* Only inherit from disabled flag */ curproxy->options = defproxy->options; diff --git a/src/server.c b/src/server.c index 272219534..acf397e55 100644 --- a/src/server.c +++ b/src/server.c @@ -2706,7 +2706,7 @@ static void srv_ssl_settings_cpy(struct server *srv, const struct server *src) /* is the current proxy's default server and SSL is enabled */ BUG_ON(src->ssl_ctx.ctx != NULL); /* the SSL_CTX must never be initialized in a default-server */ - if (srv->proxy && src == &srv->proxy->defsrv && src->use_ssl == 1) + if (srv->proxy && src == srv->proxy->defsrv && src->use_ssl == 1) srv->flags |= SRV_F_DEFSRV_USE_SSL; if (src->ssl_ctx.ca_file != NULL) @@ -3692,13 +3692,13 @@ static int _srv_parse_init(struct server **srv, char **args, int *cur_arg, skip_addr: if (!(parse_flags & SRV_PARSE_DYNAMIC)) { /* Copy default server settings to new server */ - srv_settings_cpy(newsrv, &curproxy->defsrv, 0); + srv_settings_cpy(newsrv, curproxy->defsrv, 0); } else srv_settings_init(newsrv); HA_SPIN_INIT(&newsrv->lock); } else { - *srv = newsrv = &curproxy->defsrv; + *srv = newsrv = curproxy->defsrv; *cur_arg = 1; }