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.
This commit is contained in:
Willy Tarreau 2025-07-10 16:16:24 +02:00
parent 2414c5ce2f
commit 4ac28f07d0
4 changed files with 26 additions and 12 deletions

View File

@ -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 */

View File

@ -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);

View File

@ -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;

View File

@ -2706,7 +2706,7 @@ static void srv_ssl_settings_cpy(struct server *srv, const struct server *src)
/* <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;
}