From: Amaury Denoyelle Date: Mon, 2 Aug 2021 13:50:00 +0000 (+0200) Subject: MINOR: server: implement a refcount for dynamic servers X-Git-Tag: v2.5-dev4~58 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d6b7080cecee3450bbad8fbd5d9b100be0a2d13d;p=thirdparty%2Fhaproxy.git MINOR: server: implement a refcount for dynamic servers 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. --- diff --git a/include/haproxy/server-t.h b/include/haproxy/server-t.h index 6772db2b04..02f15fc01a 100644 --- a/include/haproxy/server-t.h +++ b/include/haproxy/server-t.h @@ -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. */ diff --git a/src/server.c b/src/server.c index 9895257616..84b9cd25a8 100644 --- a/src/server.c +++ b/src/server.c @@ -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 and its member. 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");