MEDIUM: resolvers: add a ref between servers and srv request or used SRV record

This patch add a ref into servers to register them onto the
record answer item used to set their hostnames.

It also adds a head list into 'srvrq' to register servers free
to be affected to a SRV record.

A head of a tree is also added to srvrq to put servers which
present a hotname in server state file. To re-link them fastly
to the matching record as soon an item present the same name.

This results in better performances on SRV record response
parsing.

This is an optimization but it could avoid to trigger the haproxy's
internal wathdog in some circumstances. And for this reason
it should be backported as far we can (2.0 ?)

(cherry picked from commit 3406766d57fc11478d54a6fa2d048cbfe4524a4e)
Signed-off-by: Willy Tarreau <w@1wt.eu>
diff --git a/src/server.c b/src/server.c
index a7a3812..675abdb 100644
--- a/src/server.c
+++ b/src/server.c
@@ -2164,6 +2164,7 @@
 	srv->proxy = proxy;
 	srv->pendconns = EB_ROOT;
 	LIST_APPEND(&servers_list, &srv->global_list);
+	LIST_INIT(&srv->srv_rec_item);
 	LIST_INIT(&srv->ip_rec_item);
 
 	srv->next_state = SRV_ST_RUNNING; /* early server setup */
@@ -2308,6 +2309,9 @@
 				goto err;
 		}
 #endif
+		/* append to list of servers available to receive an hostname */
+		LIST_APPEND(&newsrv->srvrq->attached_servers, &newsrv->srv_rec_item);
+
 		/* Set this new server ID. */
 		_srv_parse_set_id_from_prefix(newsrv, srv->tmpl_info.prefix, i);
 
@@ -3344,18 +3348,11 @@
 		return 1;
 
 	if (s->srvrq) {
-		struct resolv_answer_item *srv_item;
-
-		/* If DNS resolution is disabled ignore it. */
-		if (s->flags & SRV_F_NO_RESOLUTION)
-			return 1;
-
-		/* The server is based on a SRV record, thus, find the
-		 * associated answer record. If not found, it means the SRV item
-		 * has expired and this resolution must be ignored.
+		/* If DNS resolution is disabled ignore it.
+		 * This is the case if the server was associated to
+		 * a SRV record and this record is now expired.
 		 */
-		srv_item = find_srvrq_answer_record(requester);
-		if (!srv_item)
+		if (s->flags & SRV_F_NO_RESOLUTION)
 			return 1;
 	}
 
@@ -3449,7 +3446,6 @@
  */
 int srvrq_resolution_error_cb(struct resolv_requester *requester, int error_code)
 {
-	struct server *s;
 	struct resolv_srvrq *srvrq;
 	struct resolv_resolution *res;
 	struct resolvers *resolvers;
@@ -3493,20 +3489,8 @@
 				return 1;
 	}
 
-	/* Remove any associated server */
-	for (s = srvrq->proxy->srv; s != NULL; s = s->next) {
-		HA_SPIN_LOCK(SERVER_LOCK, &s->lock);
-		if (s->srvrq == srvrq) {
-			resolv_unlink_resolution(s->resolv_requester, 1);
-			srvrq_update_srv_status(s, 1);
-			memset(&s->addr, 0, sizeof(s->addr));
-			ha_free(&s->hostname);
-			ha_free(&s->hostname_dn);
-			s->hostname_dn_len = 0;
-			s->svc_port = 0;
-		}
-		HA_SPIN_UNLOCK(SERVER_LOCK, &s->lock);
-	}
+	/* Remove any associated server ref */
+	resolv_detach_from_resolution_answer_items(res,  requester, 1);
 
 	return 0;
 }
@@ -3531,7 +3515,7 @@
 	if (!snr_update_srv_status(s, 1)) {
 		memset(&s->addr, 0, sizeof(s->addr));
 		HA_SPIN_UNLOCK(SERVER_LOCK, &s->lock);
-		LIST_DEL_INIT(&s->ip_rec_item);
+		resolv_detach_from_resolution_answer_items(requester->resolution, requester, 1);
 		return 0;
 	}
 	HA_SPIN_UNLOCK(SERVER_LOCK, &s->lock);