]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: proxy: Be able to reference the defaults section used by a proxy
authorChristopher Faulet <cfaulet@haproxy.com>
Wed, 13 Oct 2021 07:50:53 +0000 (09:50 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 15 Oct 2021 12:12:19 +0000 (14:12 +0200)
A proxy may now references the defaults section it is used. To do so, a
pointer on the default proxy was added in the proxy structure. And a
refcount must be used to track proxies using a default proxy. A default
proxy is destroyed iff its refcount is equal to zero and when it drops to
zero.

All this stuff must be performed during init/deinit staged for now. All
unreferenced default proxies are removed after the configuration parsing.

This patch is mandatory to support TCP/HTTP rules in defaults sections.

include/haproxy/proxy-t.h
include/haproxy/proxy.h
src/haproxy.c
src/proxy.c

index b2285bbebd7198ead158cf98103d53ac8e954b97..20c97dab9c25f6f999d7d759de9ddeec11b48dcf 100644 (file)
@@ -275,6 +275,7 @@ struct proxy {
                struct proxy *be;               /* default backend, or NULL if none set */
                char *name;                     /* default backend name during config parse */
        } defbe;
+       struct proxy *defpx;                    /* default proxy used to init this one (may be NULL) */
        struct list acl;                        /* ACL declared on this proxy */
        struct list http_req_rules;             /* HTTP request rules: allow/deny/... */
        struct list http_res_rules;             /* HTTP response rules: allow/deny/... */
@@ -421,6 +422,7 @@ struct proxy {
                struct list listeners;          /* list of listeners belonging to this frontend */
                struct list errors;             /* list of all custom error files */
                struct arg_list args;           /* sample arg list that need to be resolved */
+               unsigned int refcount;          /* refcount on this proxy (only used for default proxy for now) */
                struct ebpt_node by_name;       /* proxies are stored sorted by name here */
                char *logformat_string;         /* log format string */
                char *lfs_file;                 /* file name where the logformat string appears (strdup) */
index e47a577fed0b7ee59f8b50864d2266b760e81403..1fc7a09828434ff94afb2cd6e5e3c503bda2c969 100644 (file)
@@ -61,7 +61,9 @@ void init_new_proxy(struct proxy *p);
 void proxy_preset_defaults(struct proxy *defproxy);
 void proxy_free_defaults(struct proxy *defproxy);
 void proxy_destroy_defaults(struct proxy *px);
-void proxy_destroy_all_defaults(void);
+void proxy_destroy_all_unref_defaults(void);
+void proxy_ref_defaults(struct proxy *px, struct proxy *defpx);
+void proxy_unref_defaults(struct proxy *px);
 struct proxy *alloc_new_proxy(const char *name, unsigned int cap,
                               char **errmsg);
 struct proxy *parse_new_proxy(const char *name, unsigned int cap,
index 3c41c86fb255acdedafc7e4912b9e749a3b944d3..e3ccea77e7fea1be95cce7796cfdf019119a1626 100644 (file)
@@ -1990,8 +1990,9 @@ static void init(int argc, char **argv)
                ha_warning("a master CLI socket was defined, but master-worker mode (-W) is not enabled.\n");
        }
 
-       /* defaults sections are not needed anymore */
-       proxy_destroy_all_defaults();
+       /* destroy unreferenced defaults proxies  */
+       proxy_destroy_all_unref_defaults();
+
 
        err_code |= check_config_validity();
        for (px = proxies_list; px; px = px->next) {
@@ -2483,6 +2484,9 @@ void deinit(void)
                free_proxy(p0);
        }/* end while(p) */
 
+       /* destroy all referenced defaults proxies  */
+       proxy_destroy_all_unref_defaults();
+
        while (ua) {
                struct stat_scope *scope, *scopep;
 
index c99f3a53a5d44cebcc264cb7da339b5d263dafe7..36e278321f6adb8be8d9b4d5d02d44bae19ece13 100644 (file)
@@ -146,6 +146,7 @@ void free_proxy(struct proxy *p)
        if (!p)
                return;
 
+       proxy_unref_defaults(p);
        free(p->conf.file);
        free(p->id);
        free(p->cookie_name);
@@ -1471,22 +1472,57 @@ void proxy_destroy_defaults(struct proxy *px)
                return;
        if (!(px->cap & PR_CAP_DEF))
                return;
+       BUG_ON(px->conf.refcount != 0);
        ebpt_delete(&px->conf.by_name);
        proxy_free_defaults(px);
        free(px);
 }
 
-void proxy_destroy_all_defaults()
+/* delete all unreferenced default proxies. A default proxy is unreferenced if
+ * its refcount is equal to zero.
+ */
+void proxy_destroy_all_unref_defaults()
 {
        struct ebpt_node *n;
 
-       while ((n = ebpt_first(&defproxy_by_name))) {
+       n = ebpt_first(&defproxy_by_name);
+       while (n) {
                struct proxy *px = container_of(n, struct proxy, conf.by_name);
                BUG_ON(!(px->cap & PR_CAP_DEF));
-               proxy_destroy_defaults(px);
+               n = ebpt_next(n);
+               if (!px->conf.refcount)
+                       proxy_destroy_defaults(px);
        }
 }
 
+/* Add a reference on the default proxy <defpx> for the proxy <px> Nothing is
+ * done if <px> already references <defpx>. Otherwise, the default proxy
+ * refcount is incremented by one. For now, this operation is not thread safe
+ * and is perform during init stage only.
+ */
+void proxy_ref_defaults(struct proxy *px, struct proxy *defpx)
+{
+       if (px->defpx == defpx)
+               return;
+       BUG_ON(px->defpx != NULL);
+       px->defpx = defpx;
+       defpx->conf.refcount++;
+}
+
+/* proxy <px> removes its reference on its default proxy. The default proxy
+ * refcount is decremented by one. If it was the last reference, the
+ * corresponding default proxy is destroyed. For now this operation is not
+ * thread safe and is performed during deinit staged only.
+*/
+void proxy_unref_defaults(struct proxy *px)
+{
+       if (px->defpx == NULL)
+               return;
+       if (!--px->defpx->conf.refcount)
+               proxy_destroy_defaults(px->defpx);
+       px->defpx = NULL;
+}
+
 /* Allocates a new proxy <name> of type <cap>.
  * Returns the proxy instance on success. On error, NULL is returned.
  */