]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: server: implement a refcount for dynamic servers
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 2 Aug 2021 13:50:00 +0000 (15:50 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 6 Aug 2021 09:09:48 +0000 (11:09 +0200)
It is necessary to have a refcount mechanism on dynamic servers to be
able to enable check support. Indeed, when deleting a dynamic server
with check activated, the check will be asynchronously removed. This is
mandatory to properly free the check resources in a thread-safe manner.
The server instance must be kept alive for this.

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

index 6772db2b040dd5cd6be1412dfc79c9e21c77feb5..02f15fc01a9b61afc837753eef43e6d3511993e2 100644 (file)
@@ -259,6 +259,8 @@ struct server {
        unsigned cumulative_weight;             /* weight of servers prior to this one in the same group, for chash balancing */
        int maxqueue;                           /* maximum number of pending connections allowed */
 
+       uint refcount_dynsrv;                   /* refcount used for dynamic servers */
+
        /* The elements below may be changed on every single request by any
         * thread, and generally at the same time.
         */
index 9895257616be4408c2ff264b182d2d78da5b99f9..84b9cd25a8d565d2b0420bb70d28bd91c4ba55f9 100644 (file)
@@ -2196,10 +2196,32 @@ struct server *new_server(struct proxy *proxy)
        return srv;
 }
 
+/* Increment the dynamic server refcount. */
+static void srv_use_dynsrv(struct server *srv)
+{
+       BUG_ON(!(srv->flags & SRV_F_DYNAMIC));
+       HA_ATOMIC_INC(&srv->refcount_dynsrv);
+}
+
+/* Decrement the dynamic server refcount. */
+static uint srv_release_dynsrv(struct server *srv)
+{
+       BUG_ON(!(srv->flags & SRV_F_DYNAMIC));
+       return HA_ATOMIC_SUB_FETCH(&srv->refcount_dynsrv, 1);
+}
+
 /* Deallocate a server <srv> and its member. <srv> must be allocated.
  */
 void free_server(struct server *srv)
 {
+       /* For dynamic servers, decrement the reference counter. Only free the
+        * server when reaching zero.
+        */
+       if (srv->flags & SRV_F_DYNAMIC) {
+               if (srv_release_dynsrv(srv))
+                       return;
+       }
+
        task_destroy(srv->warmup);
        task_destroy(srv->srvrq_check);
 
@@ -4590,6 +4612,7 @@ static int cli_parse_add_server(char **args, char *payload, struct appctx *appct
        ebis_insert(&be->conf.used_server_name, &srv->conf.name);
        ebis_insert(&be->used_server_addr, &srv->addr_node);
 
+       srv_use_dynsrv(srv);
        thread_release();
 
        ha_notice("New server registered.\n");