]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: proxy: extend global tune.defaults.purge for default-server
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 8 Jul 2026 08:30:51 +0000 (10:30 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 3 Aug 2026 14:52:09 +0000 (16:52 +0200)
Previous patch changes behavior for default-server. They are now
preserved after configuration during the whole process lifetime as
dynamic servers may need them. A default-server is still purge though if
it does not contain any particular setting.

This relation between dynamic and default-server is similar to the one
between dynamic backends and named default proxies sections, which are
also kept by default at runtime.

This patch extends tune.defaults.purge keyword which was previously used
to force cleanup of named defaults section on post parsing. This now
support an extra argument to instruct the type of elements to remove :
supported values are "proxies" for named defaults sections and "servers"
for default-server.

Without any argument, the option only forces clean up of named defaults
sections. This is the simplest method to preserve backward compatibility
with previous releases.

This new setting requires a dedicated code block for default-server
purgeing in check_config_validity(). This cannot be performed during
post-section parsing as this is a global setting which can be defined
later.

doc/configuration.txt
include/haproxy/global-t.h
src/cfgparse-global.c
src/cfgparse.c

index c13837f7c026020acd090ca79266cb595966372f..a52179c3a3ccd7515dbe81e40093057693c38b9d 100644 (file)
@@ -4225,18 +4225,36 @@ tune.comp.maxlevel <number>
   Each stream using compression initializes the compression algorithm with
   this value. The default value is 1.
 
-tune.defaults.purge
-  For dynamic backends support, all named defaults sections are now kept in
-  memory after parsing. This is necessary as backend added at runtime must be
-  based on a named defaults for its configuration.
-
-  This may consume significant memory if the number of defaults instances is
-  important. In this case and if dynamic backend feature is unnecessary, it's
-  possible to use this option to force deletion of defaults section after
-  parsing. It is still mandatory though to keep referenced defaults section
-  which contain settings whose cannot be copied by their referencing proxies.
-  For example, this is the case if the defaults section defines TCP/HTTP rules
-  or a tcpcheck ruleset.
+tune.defaults.purge [<element[,...]>]
+  Define what default instances to purge after configuration parsing.
+
+  The elements to be purged are defined by a comma-delimited list of tokens.
+  The currently supported entries are :
+    - "proxies" to purge "defaults" sections
+    - "servers" to purge "default-server" instances
+
+  If the list is empty, only proxies "defaults" sections will be purged.
+
+  Default-server instances are kept in memory after parsing as they may be
+  reused for dynamic servers added at runtime. Similarly, named defaults
+  proxies sections are preserved as dynamic backends rely on them.
+
+  This may consume a noticeable amount of memory if the number of default
+  instances is important. It's possible to reclaim this memory after the
+  configuration parsing if dynamic features are unneeded.
+
+  In any case, referenced "defaults" sections which contain settings which
+  cannot be copied by their referencing proxies (e.g. TCP/HTTP rules or
+  tcpcheck ruleset) will be preserved, regardless of the global purge setting.
+
+  Example:
+      # reclaim the maximum memory possible
+      tune.defaults.purge proxies,servers
+
+      # purge proxies defaults sections
+      # both syntax are equivalent
+      tune.defaults.purge
+      tune.defaults.purge proxies
 
 tune.disable-fast-forward
   Disables the data fast-forwarding. It is a mechanism to optimize the data
@@ -7380,9 +7398,11 @@ default-server [from <origin>] [param*]
 
   A default-server with no parameter set will automatically be purged after
   parsing. As such, a final "default-server from none" statement will be
-  sufficient to release this unused memory.
+  sufficient to release this unused memory, regardless of the global setting
+  "tune.defaults.purge" value.
 
-  See also: "server" and section 5 about server options
+  See also: "server", section 5 about server options and global
+    "tune.defaults.purge" option
 
 
 default_backend <backend>
index b02462ddf8f46a51984eb5adb1d5ac725ed98108..b467f3353a3658f7700dfde19440d721ad107634 100644 (file)
@@ -80,7 +80,7 @@
 #define GTUNE_DISABLE_ACTIVE_CLOSE (1<<22)
 #define GTUNE_QUICK_EXIT         (1<<23)
 #define GTUNE_COLLECT_LIBS       (1<<24)
-/* (1<<25) unused */
+#define GTUNE_PURGE_DEF_SRV      (1<<25)
 #define GTUNE_USE_FAST_FWD       (1<<26)
 #define GTUNE_LISTENER_MQ_FAIR   (1<<27)
 #define GTUNE_LISTENER_MQ_OPT    (1<<28)
index 34200cc411687c9dca902777be87af6fcde0b7b2..e0b12f29e24e3763f49132b349ed9c41354d2c0d 100644 (file)
@@ -1433,7 +1433,27 @@ static int cfg_parse_global_tune_opts(char **args, int section_type,
                return 0;
        }
        else if (strcmp(args[0], "tune.defaults.purge") == 0) {
-               global.tune.options |= GTUNE_PURGE_DEFAULTS;
+               if (args[1]) {
+                       struct ist arg = ist(args[1]);
+                       do {
+                               struct ist token = istsplit(&arg, ',');
+
+                               if (isteq(token, ist("proxies"))) {
+                                       global.tune.options |= GTUNE_PURGE_DEFAULTS;
+                               }
+                               else if (isteq(token, ist("servers"))) {
+                                       global.tune.options |= GTUNE_PURGE_DEF_SRV;
+                               }
+                               else {
+                                       memprintf(err, "'%s' unknown directive '%s'.", args[0], ist0(token));
+                                       return -1;
+                               }
+                       } while (istlen(arg));
+               }
+               else {
+                       /* default value if no argument : purge defaults proxies. */
+                       global.tune.options |= GTUNE_PURGE_DEFAULTS;
+               }
        }
        else if (strcmp(args[0], "tune.pattern.cache-size") == 0) {
                if (*(args[1]) == 0) {
index 2e538ed669ac277a16dba8944ce1dc3f46a0e5d3..78d298ec9ca5cfb1070b5b75998735577e966a14 100644 (file)
@@ -2429,6 +2429,14 @@ init_proxies_list_stage1:
                        cfgerr++;
                }
 
+               /* Remove default-server if tune.defaults.purge is set for it. */
+               if (curproxy->cap & PR_CAP_BE && (global.tune.options & GTUNE_PURGE_DEF_SRV)) {
+                       if (curproxy->defsrv) {
+                               srv_free_params(curproxy->defsrv);
+                               srv_free(&curproxy->defsrv);
+                       }
+               }
+
                if (curproxy->flags & PR_FL_DISABLED) {
                        /* ensure we don't keep listeners uselessly bound. We
                         * can't disable their listeners yet (fdtab not