[MAJOR] session: remove the ->srv pointer from struct session

This one has been removed and is now totally superseded by ->target.
To get the server, one must use target_srv(&s->target) instead of
s->srv now.

The function ensures that non-server targets still return NULL.
diff --git a/include/proto/stream_interface.h b/include/proto/stream_interface.h
index 5c198dc..ec8d5d0 100644
--- a/include/proto/stream_interface.h
+++ b/include/proto/stream_interface.h
@@ -88,6 +88,13 @@
 	return a->type == b->type && a->ptr.v == b->ptr.v;
 }
 
+static inline struct server *target_srv(struct target *t)
+{
+	if (!t || t->type != TARG_TYPE_SERVER)
+		return NULL;
+	return t->ptr.s;
+}
+
 #endif /* _PROTO_STREAM_INTERFACE_H */
 
 /*
diff --git a/include/types/session.h b/include/types/session.h
index de87607..2ac2232 100644
--- a/include/types/session.h
+++ b/include/types/session.h
@@ -168,7 +168,6 @@
 	struct buffer *req;			/* request buffer */
 	struct buffer *rep;			/* response buffer */
 	struct stream_interface si[2];          /* client and server stream interfaces */
-	struct server *srv;			/* the server the session will be running or has been running on */
 	struct server *srv_conn;		/* session already has a slot on a server and is not in queue */
 	struct target target;			/* target to use for this session */
 	struct pendconn *pend_pos;		/* if not NULL, points to the position in the pending queue */
diff --git a/src/backend.c b/src/backend.c
index 8367328..7a9e0c6 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -446,7 +446,7 @@
  *
  * This function MAY NOT be called with SN_ASSIGNED already set. If the session
  * had a server previously assigned, it is rebalanced, trying to avoid the same
- * server, which should still be present in s->srv before the call.
+ * server, which should still be present in target_srv(&s->target) before the call.
  * The function tries to keep the original connection slot if it reconnects to
  * the same server, otherwise it releases it and tries to offer it.
  *
@@ -459,8 +459,8 @@
  *   SRV_STATUS_INTERNAL for other unrecoverable errors.
  *
  * Upon successful return, the session flag SN_ASSIGNED is set to indicate that
- * it does not need to be called anymore. This means that s->srv can be trusted
- * in balance and direct modes.
+ * it does not need to be called anymore. This means that target_srv(&s->target)
+ * can be trusted in balance and direct modes.
  *
  */
 
@@ -468,7 +468,7 @@
 {
 
 	struct server *conn_slot;
-	struct server *prev_srv;
+	struct server *srv, *prev_srv;
 	int err;
 
 #ifdef DEBUG_FULL
@@ -479,7 +479,7 @@
 	if (unlikely(s->pend_pos || s->flags & SN_ASSIGNED))
 		goto out_err;
 
-	prev_srv  = s->srv;
+	prev_srv  = target_srv(&s->target);
 	conn_slot = s->srv_conn;
 
 	/* We have to release any connection slot before applying any LB algo,
@@ -488,12 +488,12 @@
 	if (conn_slot)
 		sess_change_server(s, NULL);
 
-	/* We will now try to find the good server and store it into <s->srv>.
-	 * Note that <s->srv> may be NULL in case of dispatch or proxy mode,
+	/* We will now try to find the good server and store it into <target_srv(&s->target)>.
+	 * Note that <target_srv(&s->target)> may be NULL in case of dispatch or proxy mode,
 	 * as well as if no server is available (check error code).
 	 */
 
-	s->srv = NULL;
+	srv = NULL;
 	clear_target(&s->target);
 
 	if (s->be->lbprm.algo & BE_LB_KIND) {
@@ -510,20 +510,20 @@
 		 */
 		switch (s->be->lbprm.algo & BE_LB_LKUP) {
 		case BE_LB_LKUP_RRTREE:
-			s->srv = fwrr_get_next_server(s->be, prev_srv);
+			srv = fwrr_get_next_server(s->be, prev_srv);
 			break;
 
 		case BE_LB_LKUP_LCTREE:
-			s->srv = fwlc_get_next_server(s->be, prev_srv);
+			srv = fwlc_get_next_server(s->be, prev_srv);
 			break;
 
 		case BE_LB_LKUP_CHTREE:
 		case BE_LB_LKUP_MAP:
 			if ((s->be->lbprm.algo & BE_LB_KIND) == BE_LB_KIND_RR) {
 				if (s->be->lbprm.algo & BE_LB_LKUP_CHTREE)
-					s->srv = chash_get_next_server(s->be, prev_srv);
+					srv = chash_get_next_server(s->be, prev_srv);
 				else
-					s->srv = map_get_server_rr(s->be, prev_srv);
+					srv = map_get_server_rr(s->be, prev_srv);
 				break;
 			}
 			else if ((s->be->lbprm.algo & BE_LB_KIND) != BE_LB_KIND_HI) {
@@ -544,18 +544,18 @@
 					goto out;
 				}
 		
-				s->srv = get_server_sh(s->be,
-						       (void *)&((struct sockaddr_in *)&s->req->prod->addr.c.from)->sin_addr,
-						       len);
+				srv = get_server_sh(s->be,
+						    (void *)&((struct sockaddr_in *)&s->req->prod->addr.c.from)->sin_addr,
+						    len);
 				break;
 
 			case BE_LB_HASH_URI:
 				/* URI hashing */
 				if (s->txn.req.msg_state < HTTP_MSG_BODY)
 					break;
-				s->srv = get_server_uh(s->be,
-						       s->txn.req.sol + s->txn.req.sl.rq.u,
-						       s->txn.req.sl.rq.u_l);
+				srv = get_server_uh(s->be,
+						    s->txn.req.sol + s->txn.req.sl.rq.u,
+						    s->txn.req.sl.rq.u_l);
 				break;
 
 			case BE_LB_HASH_PRM:
@@ -563,24 +563,24 @@
 				if (s->txn.req.msg_state < HTTP_MSG_BODY)
 					break;
 
-				s->srv = get_server_ph(s->be,
-						       s->txn.req.sol + s->txn.req.sl.rq.u,
-						       s->txn.req.sl.rq.u_l);
+				srv = get_server_ph(s->be,
+						    s->txn.req.sol + s->txn.req.sl.rq.u,
+						    s->txn.req.sl.rq.u_l);
 
-				if (!s->srv && s->txn.meth == HTTP_METH_POST)
-					s->srv = get_server_ph_post(s);
+				if (!srv && s->txn.meth == HTTP_METH_POST)
+					srv = get_server_ph_post(s);
 				break;
 
 			case BE_LB_HASH_HDR:
 				/* Header Parameter hashing */
 				if (s->txn.req.msg_state < HTTP_MSG_BODY)
 					break;
-				s->srv = get_server_hh(s);
+				srv = get_server_hh(s);
 				break;
 
 			case BE_LB_HASH_RDP:
 				/* RDP Cookie hashing */
-				s->srv = get_server_rch(s);
+				srv = get_server_rch(s);
 				break;
 
 			default:
@@ -592,11 +592,11 @@
 			/* If the hashing parameter was not found, let's fall
 			 * back to round robin on the map.
 			 */
-			if (!s->srv) {
+			if (!srv) {
 				if (s->be->lbprm.algo & BE_LB_LKUP_CHTREE)
-					s->srv = chash_get_next_server(s->be, prev_srv);
+					srv = chash_get_next_server(s->be, prev_srv);
 				else
-					s->srv = map_get_server_rr(s->be, prev_srv);
+					srv = map_get_server_rr(s->be, prev_srv);
 			}
 
 			/* end of map-based LB */
@@ -608,16 +608,15 @@
 			goto out;
 		}
 
-		if (!s->srv) {
+		if (!srv) {
 			err = SRV_STATUS_FULL;
 			goto out;
 		}
-		else if (s->srv != prev_srv) {
+		else if (srv != prev_srv) {
 			s->be->counters.cum_lbconn++;
-			s->srv->counters.cum_lbconn++;
+			srv->counters.cum_lbconn++;
 		}
-
-		set_target_server(&s->target, s->srv);
+		set_target_server(&s->target, srv);
 	}
 	else if ((s->be->options2 & PR_O2_DISPATCH) || (s->be->options & PR_O_TRANSP)) {
 		set_target_proxy(&s->target, s->be);
@@ -639,8 +638,8 @@
 	 * else if we don't need it anymore.
 	 */
 	if (conn_slot) {
-		if (conn_slot == s->srv) {
-			sess_change_server(s, s->srv);
+		if (conn_slot == srv) {
+			sess_change_server(s, srv);
 		} else {
 			if (may_dequeue_tasks(conn_slot, s->be))
 				process_srv_queue(conn_slot);
@@ -676,7 +675,7 @@
 		if (!(s->flags & SN_ASSIGNED))
 			return SRV_STATUS_INTERNAL;
 
-		s->req->cons->addr.s.to = s->srv->addr;
+		s->req->cons->addr.s.to = target_srv(&s->target)->addr;
 
 		if (!s->req->cons->addr.s.to.sin_addr.s_addr) {
 			/* if the server has no address, we use the same address
@@ -693,7 +692,7 @@
 
 		/* if this server remaps proxied ports, we'll use
 		 * the port the client connected to with an offset. */
-		if (s->srv->state & SRV_MAPPORTS) {
+		if (target_srv(&s->target)->state & SRV_MAPPORTS) {
 			if (!(s->be->options & PR_O_TRANSP) && !(s->flags & SN_FRT_ADDR_SET))
 				get_frt_addr(s);
 			if (s->req->prod->addr.c.to.ss_family == AF_INET) {
@@ -747,10 +746,10 @@
  * Returns :
  *
  *   SRV_STATUS_OK       if everything is OK.
- *   SRV_STATUS_NOSRV    if no server is available. s->srv = NULL.
+ *   SRV_STATUS_NOSRV    if no server is available. target_srv(&s->target) = NULL.
  *   SRV_STATUS_QUEUED   if the connection has been queued.
  *   SRV_STATUS_FULL     if the server(s) is/are saturated and the
- *                       connection could not be queued in s->srv,
+ *                       connection could not be queued at the server's,
  *                       which may be NULL if we queue on the backend.
  *   SRV_STATUS_INTERNAL for other unrecoverable errors.
  *
@@ -758,6 +757,7 @@
 int assign_server_and_queue(struct session *s)
 {
 	struct pendconn *p;
+	struct server *srv;
 	int err;
 
 	if (s->pend_pos)
@@ -765,7 +765,7 @@
 
 	err = SRV_STATUS_OK;
 	if (!(s->flags & SN_ASSIGNED)) {
-		struct server *prev_srv = s->srv;
+		struct server *prev_srv = target_srv(&s->target);
 
 		err = assign_server(s);
 		if (prev_srv) {
@@ -778,7 +778,7 @@
 			 *  - if the server remained the same : update retries.
 			 */
 
-			if (prev_srv != s->srv) {
+			if (prev_srv != target_srv(&s->target)) {
 				if ((s->txn.flags & TX_CK_MASK) == TX_CK_VALID) {
 					s->txn.flags &= ~TX_CK_MASK;
 					s->txn.flags |= TX_CK_DOWN;
@@ -796,22 +796,23 @@
 	switch (err) {
 	case SRV_STATUS_OK:
 		/* we have SN_ASSIGNED set */
-		if (!s->srv)
+		srv = target_srv(&s->target);
+		if (!srv)
 			return SRV_STATUS_OK;   /* dispatch or proxy mode */
 
 		/* If we already have a connection slot, no need to check any queue */
-		if (s->srv_conn == s->srv)
+		if (s->srv_conn == srv)
 			return SRV_STATUS_OK;
 
 		/* OK, this session already has an assigned server, but no
 		 * connection slot yet. Either it is a redispatch, or it was
 		 * assigned from persistence information (direct mode).
 		 */
-		if ((s->flags & SN_REDIRECTABLE) && s->srv->rdr_len) {
+		if ((s->flags & SN_REDIRECTABLE) && srv->rdr_len) {
 			/* server scheduled for redirection, and already assigned. We
 			 * don't want to go further nor check the queue.
 			 */
-			sess_change_server(s, s->srv); /* not really needed in fact */
+			sess_change_server(s, srv); /* not really needed in fact */
 			return SRV_STATUS_OK;
 		}
 
@@ -820,10 +821,10 @@
 		 * is set on the server, we must also check that the server's queue is
 		 * not full, in which case we have to return FULL.
 		 */
-		if (s->srv->maxconn &&
-		    (s->srv->nbpend || s->srv->served >= srv_dynamic_maxconn(s->srv))) {
+		if (srv->maxconn &&
+		    (srv->nbpend || srv->served >= srv_dynamic_maxconn(srv))) {
 
-			if (s->srv->maxqueue > 0 && s->srv->nbpend >= s->srv->maxqueue)
+			if (srv->maxqueue > 0 && srv->nbpend >= srv->maxqueue)
 				return SRV_STATUS_FULL;
 
 			p = pendconn_add(s);
@@ -834,7 +835,7 @@
 		}
 
 		/* OK, we can use this server. Let's reserve our place */
-		sess_change_server(s, s->srv);
+		sess_change_server(s, srv);
 		return SRV_STATUS_OK;
 
 	case SRV_STATUS_FULL:
@@ -863,10 +864,12 @@
 static void assign_tproxy_address(struct session *s)
 {
 #if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
-	if (s->srv != NULL && s->srv->state & SRV_BIND_SRC) {
-		switch (s->srv->state & SRV_TPROXY_MASK) {
+	struct server *srv = target_srv(&s->target);
+
+	if (srv && srv->state & SRV_BIND_SRC) {
+		switch (srv->state & SRV_TPROXY_MASK) {
 		case SRV_TPROXY_ADDR:
-			s->req->cons->addr.s.from = *(struct sockaddr_in *)&s->srv->tproxy_addr;
+			s->req->cons->addr.s.from = *(struct sockaddr_in *)&srv->tproxy_addr;
 			break;
 		case SRV_TPROXY_CLI:
 		case SRV_TPROXY_CIP:
@@ -874,14 +877,14 @@
 			s->req->cons->addr.s.from = *(struct sockaddr_in *)&s->req->prod->addr.c.from;
 			break;
 		case SRV_TPROXY_DYN:
-			if (s->srv->bind_hdr_occ) {
+			if (srv->bind_hdr_occ) {
 				/* bind to the IP in a header */
 				s->req->cons->addr.s.from.sin_port = 0;
 				s->req->cons->addr.s.from.sin_addr.s_addr = htonl(get_ip_from_hdr2(&s->txn.req,
-										s->srv->bind_hdr_name,
-										s->srv->bind_hdr_len,
+										srv->bind_hdr_name,
+										srv->bind_hdr_len,
 										&s->txn.hdr_idx,
-										s->srv->bind_hdr_occ));
+										srv->bind_hdr_occ));
 			}
 			break;
 		default:
@@ -919,7 +922,7 @@
 
 /*
  * This function initiates a connection to the server assigned to this session
- * (s->srv, s->target, s->req->cons->addr.s.to). It will assign a server if none
+ * (s->target, s->req->cons->addr.s.to). It will assign a server if none
  * is assigned yet.
  * It can return one of :
  *  - SN_ERR_NONE if everything's OK
@@ -932,6 +935,7 @@
  */
 int connect_server(struct session *s)
 {
+	struct server *srv;
 	int err;
 
 	if (!(s->flags & SN_ADDR_SET)) {
@@ -957,13 +961,14 @@
 	if (err != SN_ERR_NONE)
 		return err;
 
-	if (s->srv) {
+	srv = target_srv(&s->target);
+	if (srv) {
 		s->flags |= SN_CURR_SESS;
-		s->srv->cur_sess++;
-		if (s->srv->cur_sess > s->srv->counters.cur_sess_max)
-			s->srv->counters.cur_sess_max = s->srv->cur_sess;
+		srv->cur_sess++;
+		if (srv->cur_sess > srv->counters.cur_sess_max)
+			srv->counters.cur_sess_max = srv->cur_sess;
 		if (s->be->lbprm.server_take_conn)
-			s->be->lbprm.server_take_conn(s->srv);
+			s->be->lbprm.server_take_conn(srv);
 	}
 
 	return SN_ERR_NONE;  /* connection is OK */
@@ -980,6 +985,7 @@
 
 int srv_redispatch_connect(struct session *t)
 {
+	struct server *srv;
 	int conn_err;
 
 	/* We know that we don't have any connection pending, so we will
@@ -987,6 +993,8 @@
 	 */
  redispatch:
 	conn_err = assign_server_and_queue(t);
+	srv = target_srv(&t->target);
+
 	switch (conn_err) {
 	case SRV_STATUS_OK:
 		break;
@@ -996,8 +1004,8 @@
 		 * and we can redispatch to another server, or it is not and we return
 		 * 503. This only makes sense in DIRECT mode however, because normal LB
 		 * algorithms would never select such a server, and hash algorithms
-		 * would bring us on the same server again. Note that t->srv is set in
-		 * this case.
+		 * would bring us on the same server again. Note that t->target is set
+		 * in this case.
 		 */
 		if (((t->flags & (SN_DIRECT|SN_FORCE_PRST)) == SN_DIRECT) &&
 		    (t->be->options & PR_O_REDISP)) {
@@ -1007,15 +1015,15 @@
 
 		if (!t->req->cons->err_type) {
 			t->req->cons->err_type = SI_ET_QUEUE_ERR;
-			t->req->cons->err_loc = t->srv;
+			t->req->cons->err_loc = srv;
 		}
 
-		t->srv->counters.failed_conns++;
+		srv->counters.failed_conns++;
 		t->be->counters.failed_conns++;
 		return 1;
 
 	case SRV_STATUS_NOSRV:
-		/* note: it is guaranteed that t->srv == NULL here */
+		/* note: it is guaranteed that srv == NULL here */
 		if (!t->req->cons->err_type) {
 			t->req->cons->err_type = SI_ET_CONN_ERR;
 			t->req->cons->err_loc = NULL;
@@ -1034,18 +1042,18 @@
 	default:
 		if (!t->req->cons->err_type) {
 			t->req->cons->err_type = SI_ET_CONN_OTHER;
-			t->req->cons->err_loc = t->srv;
+			t->req->cons->err_loc = srv;
 		}
 
-		if (t->srv)
-			srv_inc_sess_ctr(t->srv);
-		if (t->srv)
-			t->srv->counters.failed_conns++;
+		if (srv)
+			srv_inc_sess_ctr(srv);
+		if (srv)
+			srv->counters.failed_conns++;
 		t->be->counters.failed_conns++;
 
 		/* release other sessions waiting for this server */
-		if (may_dequeue_tasks(t->srv, t->be))
-			process_srv_queue(t->srv);
+		if (may_dequeue_tasks(srv, t->be))
+			process_srv_queue(srv);
 		return 1;
 	}
 	/* if we get here, it's because we got SRV_STATUS_OK, which also
@@ -1110,7 +1118,6 @@
 			if ((srv->state & SRV_RUNNING) || (px->options & PR_O_PERSIST)) {
 				/* we found the server and it is usable */
 				s->flags |= SN_DIRECT | SN_ASSIGNED;
-				s->srv = srv;
 				set_target_server(&s->target, srv);
 				break;
 			}
@@ -1414,12 +1421,12 @@
 acl_fetch_srv_id(struct proxy *px, struct session *l4, void *l7, int dir,
                 struct acl_expr *expr, struct acl_test *test) {
 
-	if (!l4->srv)
+	if (!target_srv(&l4->target))
 		return 0;
 
 	test->flags = ACL_TEST_F_READ_ONLY;
 
-	test->i = l4->srv->puid;
+	test->i = target_srv(&l4->target)->puid;
 
 	return 1;
 }
diff --git a/src/checks.c b/src/checks.c
index 521de1d..ba3e745 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -349,7 +349,6 @@
 		p = pendconn_from_px(s->proxy);
 		if (!p)
 			break;
-		p->sess->srv = s;
 		set_target_server(&p->sess->target, s);
 		sess = p->sess;
 		pendconn_free(p);
diff --git a/src/dumpstats.c b/src/dumpstats.c
index 3411ac3..ed577ad 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -2746,8 +2746,8 @@
 		chunk_printf(&msg,
 			     "  backend=%s (id=%u mode=%s) server=%s (id=%u)\n",
 			     sess->be->id, sess->be->uuid, sess->be->mode ? "http" : "tcp",
-			     sess->srv ? sess->srv->id : "<none>",
-			     sess->srv ? sess->srv->puid : 0);
+			     target_srv(&sess->target) ? target_srv(&sess->target)->id : "<none>",
+			     target_srv(&sess->target) ? target_srv(&sess->target)->puid : 0);
 
 		chunk_printf(&msg,
 			     "  task=%p (state=0x%02x nice=%d calls=%d exp=%s%s)\n",
@@ -2953,7 +2953,7 @@
 					     ntohs(((struct sockaddr_in *)&curr_sess->si[0].addr.c.from)->sin_port),
 					     curr_sess->fe->id,
 					     curr_sess->be->id,
-					     curr_sess->srv ? curr_sess->srv->id : "<none>"
+					     target_srv(&curr_sess->target) ? target_srv(&curr_sess->target)->id : "<none>"
 					     );
 				break;
 			case AF_INET6:
@@ -2967,7 +2967,7 @@
 					     ntohs(((struct sockaddr_in6 *)&curr_sess->si[0].addr.c.from)->sin6_port),
 					     curr_sess->fe->id,
 					     curr_sess->be->id,
-					     curr_sess->srv ? curr_sess->srv->id : "<none>"
+					     target_srv(&curr_sess->target) ? target_srv(&curr_sess->target)->id : "<none>"
 					     );
 
 				break;
@@ -2977,7 +2977,7 @@
 					     curr_sess->listener->luid,
 					     curr_sess->fe->id,
 					     curr_sess->be->id,
-					     curr_sess->srv ? curr_sess->srv->id : "<none>"
+					     target_srv(&curr_sess->target) ? target_srv(&curr_sess->target)->id : "<none>"
 					     );
 				break;
 			}
diff --git a/src/log.c b/src/log.c
index de1bf2f..f90ec90 100644
--- a/src/log.c
+++ b/src/log.c
@@ -30,6 +30,7 @@
 #include <types/global.h>
 
 #include <proto/log.h>
+#include <proto/stream_interface.h>
 
 const char *log_facilities[NB_LOG_FACILITIES] = {
 	"kern", "user", "mail", "daemon",
@@ -383,7 +384,7 @@
 		 (tolog & LW_BYTES) ? "" : "+", s->logs.bytes_out,
 		 sess_term_cond[(s->flags & SN_ERR_MASK) >> SN_ERR_SHIFT],
 		 sess_fin_state[(s->flags & SN_FINST_MASK) >> SN_FINST_SHIFT],
-		 actconn, fe->feconn, be->beconn, s->srv ? s->srv->cur_sess : 0,
+		 actconn, fe->feconn, be->beconn, target_srv(&s->target) ? target_srv(&s->target)->cur_sess : 0,
 		 (s->flags & SN_REDISP)?"+":"",
 		 (s->req->cons->conn_retries>0)?(be->conn_retries - s->req->cons->conn_retries):be->conn_retries,
 		 s->logs.srv_queue_size, s->logs.prx_queue_size);
diff --git a/src/peers.c b/src/peers.c
index 3e07a27..5b8e749 100644
--- a/src/peers.c
+++ b/src/peers.c
@@ -1184,7 +1184,7 @@
 	stream_sock_prepare_interface(&s->si[1]);
 	s->si[1].release = NULL;
 
-	s->srv = s->srv_conn = NULL;
+	s->srv_conn = NULL;
 	clear_target(&s->target);
 	s->pend_pos = NULL;
 
diff --git a/src/proto_http.c b/src/proto_http.c
index 5275f2f..cbfdca2 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -745,6 +745,7 @@
 {
 	struct http_txn *txn;
 	struct chunk rdr;
+	struct server *srv;
 	char *path;
 	int len;
 
@@ -754,14 +755,16 @@
 	rdr.size = sizeof(trash);
 	memcpy(rdr.str, HTTP_302, rdr.len);
 
+	srv = target_srv(&s->target);
+
 	/* 2: add the server's prefix */
-	if (rdr.len + s->srv->rdr_len > rdr.size)
+	if (rdr.len + srv->rdr_len > rdr.size)
 		return;
 
 	/* special prefix "/" means don't change URL */
-	if (s->srv->rdr_len != 1 || *s->srv->rdr_pfx != '/') {
-		memcpy(rdr.str + rdr.len, s->srv->rdr_pfx, s->srv->rdr_len);
-		rdr.len += s->srv->rdr_len;
+	if (srv->rdr_len != 1 || *srv->rdr_pfx != '/') {
+		memcpy(rdr.str + rdr.len, srv->rdr_pfx, srv->rdr_len);
+		rdr.len += srv->rdr_len;
 	}
 
 	/* 3: add the request URI */
@@ -796,8 +799,8 @@
 	http_server_error(s, si, SN_ERR_PRXCOND, SN_FINST_C, 302, &rdr);
 
 	/* FIXME: we should increase a counter of redirects per server and per backend. */
-	if (s->srv)
-		srv_inc_sess_ctr(s->srv);
+	if (srv)
+		srv_inc_sess_ctr(srv);
 }
 
 /* Return the error message corresponding to si->err_type. It is assumed
@@ -992,7 +995,7 @@
 
 	w = snprintf(h, sizeof(tmpline) - (h - tmpline),
 	             " %d %d %d %d %d %ld %ld",
-	             actconn, fe->feconn, be->beconn, s->srv ? s->srv->cur_sess : 0,
+	             actconn, fe->feconn, be->beconn, target_srv(&s->target) ? target_srv(&s->target)->cur_sess : 0,
 	             (s->req->cons->conn_retries > 0) ? (be->conn_retries - s->req->cons->conn_retries) : be->conn_retries,
 	             s->logs.srv_queue_size, s->logs.prx_queue_size);
 
@@ -1213,7 +1216,7 @@
 		 sess_fin_state[(s->flags & SN_FINST_MASK) >> SN_FINST_SHIFT],
 		 (be->options & PR_O_COOK_ANY) ? sess_cookie[(txn->flags & TX_CK_MASK) >> TX_CK_SHIFT] : '-',
 		 (be->options & PR_O_COOK_ANY) ? sess_set_cookie[(txn->flags & TX_SCK_MASK) >> TX_SCK_SHIFT] : '-',
-		 actconn, fe->feconn, be->beconn, s->srv ? s->srv->cur_sess : 0,
+		 actconn, fe->feconn, be->beconn, target_srv(&s->target) ? target_srv(&s->target)->cur_sess : 0,
 		 (s->flags & SN_REDISP)?"+":"",
 		 (s->req->cons->conn_retries>0)?(be->conn_retries - s->req->cons->conn_retries):be->conn_retries,
 		 s->logs.srv_queue_size, s->logs.prx_queue_size, tmpline);
@@ -3937,18 +3940,17 @@
 	if (s->pend_pos)
 		pendconn_free(s->pend_pos);
 
-	if (s->srv) {
+	if (target_srv(&s->target)) {
 		if (s->flags & SN_CURR_SESS) {
 			s->flags &= ~SN_CURR_SESS;
-			s->srv->cur_sess--;
+			target_srv(&s->target)->cur_sess--;
 		}
-		if (may_dequeue_tasks(s->srv, s->be))
-			process_srv_queue(s->srv);
+		if (may_dequeue_tasks(target_srv(&s->target), s->be))
+			process_srv_queue(target_srv(&s->target));
 	}
 
 	if (unlikely(s->srv_conn))
 		sess_change_server(s, NULL);
-	s->srv = NULL;
 	clear_target(&s->target);
 
 	s->req->cons->state     = s->req->cons->prev_state = SI_ST_INI;
@@ -4231,8 +4233,8 @@
 		else if (buf->flags & BF_SHUTW) {
 			txn->rsp.msg_state = HTTP_MSG_ERROR;
 			s->be->counters.cli_aborts++;
-			if (s->srv)
-				s->srv->counters.cli_aborts++;
+			if (target_srv(&s->target))
+				target_srv(&s->target)->counters.cli_aborts++;
 			goto wait_other_side;
 		}
 	}
@@ -4514,8 +4516,8 @@
 		s->fe->counters.cli_aborts++;
 		if (s->fe != s->be)
 			s->be->counters.cli_aborts++;
-		if (s->srv)
-			s->srv->counters.cli_aborts++;
+		if (target_srv(&s->target))
+			target_srv(&s->target)->counters.cli_aborts++;
 
 		goto return_bad_req_stats_ok;
 	}
@@ -4574,8 +4576,8 @@
 	s->fe->counters.srv_aborts++;
 	if (s->fe != s->be)
 		s->be->counters.srv_aborts++;
-	if (s->srv)
-		s->srv->counters.srv_aborts++;
+	if (target_srv(&s->target))
+		target_srv(&s->target)->counters.srv_aborts++;
 
 	if (!(s->flags & SN_ERR_MASK))
 		s->flags |= SN_ERR_SRVCL;
@@ -4701,9 +4703,9 @@
 				http_capture_bad_message(&s->be->invalid_rep, s, rep, msg, msg->msg_state, s->fe);
 
 			s->be->counters.failed_resp++;
-			if (s->srv) {
-				s->srv->counters.failed_resp++;
-				health_adjust(s->srv, HANA_STATUS_HTTP_HDRRSP);
+			if (target_srv(&s->target)) {
+				target_srv(&s->target)->counters.failed_resp++;
+				health_adjust(target_srv(&s->target), HANA_STATUS_HTTP_HDRRSP);
 			}
 		abort_response:
 			buffer_auto_close(rep);
@@ -4732,9 +4734,9 @@
 				http_capture_bad_message(&s->be->invalid_rep, s, rep, msg, msg->msg_state, s->fe);
 
 			s->be->counters.failed_resp++;
-			if (s->srv) {
-				s->srv->counters.failed_resp++;
-				health_adjust(s->srv, HANA_STATUS_HTTP_READ_ERROR);
+			if (target_srv(&s->target)) {
+				target_srv(&s->target)->counters.failed_resp++;
+				health_adjust(target_srv(&s->target), HANA_STATUS_HTTP_READ_ERROR);
 			}
 
 			buffer_auto_close(rep);
@@ -4757,9 +4759,9 @@
 				http_capture_bad_message(&s->be->invalid_rep, s, rep, msg, msg->msg_state, s->fe);
 
 			s->be->counters.failed_resp++;
-			if (s->srv) {
-				s->srv->counters.failed_resp++;
-				health_adjust(s->srv, HANA_STATUS_HTTP_READ_TIMEOUT);
+			if (target_srv(&s->target)) {
+				target_srv(&s->target)->counters.failed_resp++;
+				health_adjust(target_srv(&s->target), HANA_STATUS_HTTP_READ_TIMEOUT);
 			}
 
 			buffer_auto_close(rep);
@@ -4782,9 +4784,9 @@
 				http_capture_bad_message(&s->be->invalid_rep, s, rep, msg, msg->msg_state, s->fe);
 
 			s->be->counters.failed_resp++;
-			if (s->srv) {
-				s->srv->counters.failed_resp++;
-				health_adjust(s->srv, HANA_STATUS_HTTP_BROKEN_PIPE);
+			if (target_srv(&s->target)) {
+				target_srv(&s->target)->counters.failed_resp++;
+				health_adjust(target_srv(&s->target), HANA_STATUS_HTTP_BROKEN_PIPE);
 			}
 
 			buffer_auto_close(rep);
@@ -4845,8 +4847,8 @@
 	if (n == 4)
 		session_inc_http_err_ctr(s);
 
-	if (s->srv)
-		s->srv->counters.p.http.rsp[n]++;
+	if (target_srv(&s->target))
+		target_srv(&s->target)->counters.p.http.rsp[n]++;
 
 	/* check if the response is HTTP/1.1 or above */
 	if ((msg->sl.st.v_l == 8) &&
@@ -4867,11 +4869,11 @@
 	 * and 505 are triggered on demand by client request, so we must not
 	 * count them as server failures.
 	 */
-	if (s->srv) {
+	if (target_srv(&s->target)) {
 		if (txn->status >= 100 && (txn->status < 500 || txn->status == 501 || txn->status == 505))
-			health_adjust(s->srv, HANA_STATUS_HTTP_OK);
+			health_adjust(target_srv(&s->target), HANA_STATUS_HTTP_OK);
 		else
-			health_adjust(s->srv, HANA_STATUS_HTTP_STS);
+			health_adjust(target_srv(&s->target), HANA_STATUS_HTTP_STS);
 	}
 
 	/*
@@ -5124,9 +5126,9 @@
 			if (rule_set->rsp_exp != NULL) {
 				if (apply_filters_to_response(t, rep, rule_set) < 0) {
 				return_bad_resp:
-					if (t->srv) {
-						t->srv->counters.failed_resp++;
-						health_adjust(t->srv, HANA_STATUS_HTTP_RSP);
+					if (target_srv(&t->target)) {
+						target_srv(&t->target)->counters.failed_resp++;
+						health_adjust(target_srv(&t->target), HANA_STATUS_HTTP_RSP);
 					}
 					cur_proxy->counters.failed_resp++;
 				return_srv_prx_502:
@@ -5145,8 +5147,8 @@
 
 			/* has the response been denied ? */
 			if (txn->flags & TX_SVDENY) {
-				if (t->srv)
-					t->srv->counters.failed_secu++;
+				if (target_srv(&t->target))
+					target_srv(&t->target)->counters.failed_secu++;
 
 				cur_proxy->counters.denied_resp++;
 				if (t->listener->counters)
@@ -5213,7 +5215,7 @@
 		/*
 		 * 6: add server cookie in the response if needed
 		 */
-		if ((t->srv) && (t->be->options & PR_O_COOK_INS) &&
+		if (target_srv(&t->target) && (t->be->options & PR_O_COOK_INS) &&
 		    !((txn->flags & TX_SCK_FOUND) && (t->be->options2 & PR_O2_COOK_PSV)) &&
 		    (!(t->flags & SN_DIRECT) ||
 		     ((t->be->cookie_maxidle || txn->cookie_last_date) &&
@@ -5229,13 +5231,13 @@
 			 * requests and this one isn't. Note that servers which don't have cookies
 			 * (eg: some backup servers) will return a full cookie removal request.
 			 */
-			if (!t->srv->cookie) {
+			if (!target_srv(&t->target)->cookie) {
 				len = sprintf(trash,
 					      "Set-Cookie: %s=; Expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/",
 					      t->be->cookie_name);
 			}
 			else {
-				len = sprintf(trash, "Set-Cookie: %s=%s", t->be->cookie_name, t->srv->cookie);
+				len = sprintf(trash, "Set-Cookie: %s=%s", t->be->cookie_name, target_srv(&t->target)->cookie);
 
 				if (t->be->cookie_maxidle || t->be->cookie_maxlife) {
 					/* emit last_date, which is mandatory */
@@ -5263,7 +5265,7 @@
 				goto return_bad_resp;
 
 			txn->flags &= ~TX_SCK_MASK;
-			if (t->srv->cookie && (t->flags & SN_DIRECT))
+			if (target_srv(&t->target)->cookie && (t->flags & SN_DIRECT))
 				/* the server did not change, only the date was updated */
 				txn->flags |= TX_SCK_UPDATED;
 			else
@@ -5297,18 +5299,18 @@
 			 * a set-cookie header. We'll block it as requested by
 			 * the 'checkcache' option, and send an alert.
 			 */
-			if (t->srv)
-				t->srv->counters.failed_secu++;
+			if (target_srv(&t->target))
+				target_srv(&t->target)->counters.failed_secu++;
 
 			cur_proxy->counters.denied_resp++;
 			if (t->listener->counters)
 				t->listener->counters->denied_resp++;
 
 			Alert("Blocking cacheable cookie in response from instance %s, server %s.\n",
-			      t->be->id, t->srv?t->srv->id:"<dispatch>");
+			      t->be->id, target_srv(&t->target) ? target_srv(&t->target)->id : "<dispatch>");
 			send_log(t->be, LOG_ALERT,
 				 "Blocking cacheable cookie in response from instance %s, server %s.\n",
-				 t->be->id, t->srv?t->srv->id:"<dispatch>");
+				 t->be->id, target_srv(&t->target) ? target_srv(&t->target)->id : "<dispatch>");
 			goto return_srv_prx_502;
 		}
 
@@ -5526,8 +5528,8 @@
 		if (!(s->flags & SN_ERR_MASK))
 			s->flags |= SN_ERR_SRVCL;
 		s->be->counters.srv_aborts++;
-		if (s->srv)
-			s->srv->counters.srv_aborts++;
+		if (target_srv(&s->target))
+			target_srv(&s->target)->counters.srv_aborts++;
 		goto return_bad_res_stats_ok;
 	}
 
@@ -5564,8 +5566,8 @@
 
  return_bad_res: /* let's centralize all bad responses */
 	s->be->counters.failed_resp++;
-	if (s->srv)
-		s->srv->counters.failed_resp++;
+	if (target_srv(&s->target))
+		target_srv(&s->target)->counters.failed_resp++;
 
  return_bad_res_stats_ok:
 	txn->rsp.msg_state = HTTP_MSG_ERROR;
@@ -5573,8 +5575,8 @@
 	stream_int_retnclose(res->cons, NULL);
 	res->analysers = 0;
 	s->req->analysers = 0; /* we're in data phase, we want to abort both directions */
-	if (s->srv)
-		health_adjust(s->srv, HANA_STATUS_HTTP_HDRRSP);
+	if (target_srv(&s->target))
+		health_adjust(target_srv(&s->target), HANA_STATUS_HTTP_HDRRSP);
 
 	if (!(s->flags & SN_ERR_MASK))
 		s->flags |= SN_ERR_PRXCOND;
@@ -5592,8 +5594,8 @@
 	s->fe->counters.cli_aborts++;
 	if (s->fe != s->be)
 		s->be->counters.cli_aborts++;
-	if (s->srv)
-		s->srv->counters.cli_aborts++;
+	if (target_srv(&s->target))
+		target_srv(&s->target)->counters.cli_aborts++;
 
 	if (!(s->flags & SN_ERR_MASK))
 		s->flags |= SN_ERR_CLICL;
@@ -5962,7 +5964,6 @@
 						txn->flags &= ~TX_CK_MASK;
 						txn->flags |= (srv->state & SRV_RUNNING) ? TX_CK_VALID : TX_CK_DOWN;
 						t->flags |= SN_DIRECT | SN_ASSIGNED;
-						t->srv = srv;
 						set_target_server(&t->target, srv);
 
 						break;
@@ -6373,7 +6374,6 @@
 							txn->flags &= ~TX_CK_MASK;
 							txn->flags |= (srv->state & SRV_RUNNING) ? TX_CK_VALID : TX_CK_DOWN;
 							t->flags |= SN_DIRECT | SN_ASSIGNED;
-							t->srv = srv;
 							set_target_server(&t->target, srv);
 							break;
 						} else {
@@ -6747,6 +6747,7 @@
 void manage_server_side_cookies(struct session *t, struct buffer *res)
 {
 	struct http_txn *txn = &t->txn;
+	struct server *srv;
 	int is_cookie2;
 	int cur_idx, old_idx, delta;
 	char *hdr_beg, *hdr_end, *hdr_next;
@@ -6946,6 +6947,7 @@
 				}
 			}
 
+			srv = target_srv(&t->target);
 			/* now check if we need to process it for persistence */
 			if (!(t->flags & SN_IGNORE_PRST) &&
 			    (att_end - att_beg == t->be->cookie_len) && (t->be->cookie_name != NULL) &&
@@ -6964,7 +6966,7 @@
 					 * server's cookie.
 					 */
 				}
-				else if (((t->srv) && (t->be->options & PR_O_COOK_INS)) ||
+				else if ((srv && (t->be->options & PR_O_COOK_INS)) ||
 				    ((t->flags & SN_DIRECT) && (t->be->options & PR_O_COOK_IND))) {
 					/* this cookie must be deleted */
 					if (*prev == ':' && next == hdr_end) {
@@ -6992,12 +6994,11 @@
 					txn->flags |= TX_SCK_DELETED;
 					/* and go on with next cookie */
 				}
-				else if ((t->srv) && (t->srv->cookie) &&
-					 (t->be->options & PR_O_COOK_RW)) {
+				else if (srv && srv->cookie && (t->be->options & PR_O_COOK_RW)) {
 					/* replace bytes val_beg->val_end with the cookie name associated
 					 * with this server since we know it.
 					 */
-					delta = buffer_replace2(res, val_beg, val_end, t->srv->cookie, t->srv->cklen);
+					delta = buffer_replace2(res, val_beg, val_end, srv->cookie, srv->cklen);
 					next     += delta;
 					hdr_end  += delta;
 					hdr_next += delta;
@@ -7007,19 +7008,18 @@
 					txn->flags &= ~TX_SCK_MASK;
 					txn->flags |= TX_SCK_REPLACED;
 				}
-				else if ((t->srv) && (t->srv->cookie) &&
-					 (t->be->options & PR_O_COOK_PFX)) {
+				else if (srv && srv && (t->be->options & PR_O_COOK_PFX)) {
 					/* insert the cookie name associated with this server
 					 * before existing cookie, and insert a delimiter between them..
 					 */
-					delta = buffer_replace2(res, val_beg, val_beg, t->srv->cookie, t->srv->cklen + 1);
+					delta = buffer_replace2(res, val_beg, val_beg, srv->cookie, srv->cklen + 1);
 					next     += delta;
 					hdr_end  += delta;
 					hdr_next += delta;
 					cur_hdr->len += delta;
 					http_msg_move_end(&txn->rsp, delta);
 
-					val_beg[t->srv->cklen] = COOKIE_DELIM;
+					val_beg[srv->cklen] = COOKIE_DELIM;
 					txn->flags &= ~TX_SCK_MASK;
 					txn->flags |= TX_SCK_REPLACED;
 				}
@@ -7084,7 +7084,7 @@
 			memcpy(asession->sessid, txn->sessid, t->be->appsession_len);
 			asession->sessid[t->be->appsession_len] = 0;
 
-			server_id_len = strlen(t->srv->id) + 1;
+			server_id_len = strlen(target_srv(&t->target)->id) + 1;
 			if ((asession->serverid = pool_alloc2(apools.serverid)) == NULL) {
 				Alert("Not enough Memory process_srv():asession->serverid:malloc().\n");
 				send_log(t->be, LOG_ALERT, "Not enough Memory process_srv():asession->sessid:malloc().\n");
@@ -7092,7 +7092,7 @@
 				return;
 			}
 			asession->serverid[0] = '\0';
-			memcpy(asession->serverid, t->srv->id, server_id_len);
+			memcpy(asession->serverid, target_srv(&t->target)->id, server_id_len);
 
 			asession->request_count = 0;
 			appsession_hash_insert(&(t->be->htbl_proxy), asession);
@@ -7379,7 +7379,7 @@
 
 	es->when = date; // user-visible date
 	es->sid  = s->uniq_id;
-	es->srv  = s->srv;
+	es->srv  = target_srv(&s->target);
 	es->oe   = other_end;
 	es->src  = s->req->prod->addr.c.from;
 	es->state = state;
@@ -7538,7 +7538,7 @@
 
 	s->be = s->fe;
 	s->logs.logwait = s->fe->to_log;
-	s->srv = s->srv_conn = NULL;
+	s->srv_conn = NULL;
 	clear_target(&s->target);
 	/* re-init store persistence */
 	s->store_count = 0;
diff --git a/src/queue.c b/src/queue.c
index 4994181..ae99284 100644
--- a/src/queue.c
+++ b/src/queue.c
@@ -113,10 +113,8 @@
 			return NULL;
 	} else {
 		/* pendconn exists in the proxy queue */
-		if (!ps || tv_islt(&pp->sess->logs.tv_request, &ps->sess->logs.tv_request)) {
+		if (!ps || tv_islt(&pp->sess->logs.tv_request, &ps->sess->logs.tv_request))
 			ps = pp;
-			ps->sess->srv = srv;
-		}
 	}
 	sess = ps->sess;
 	pendconn_free(ps);
@@ -124,7 +122,6 @@
 	/* we want to note that the session has now been assigned a server */
 	sess->flags |= SN_ASSIGNED;
 	set_target_server(&sess->target, srv);
-	sess->srv = srv;
 	sess->srv_conn = srv;
 	srv->served++;
 	if (px->lbprm.server_take_conn)
@@ -142,6 +139,7 @@
 struct pendconn *pendconn_add(struct session *sess)
 {
 	struct pendconn *p;
+	struct server *srv;
 
 	p = pool_alloc2(pool2_pendconn);
 	if (!p)
@@ -149,14 +147,14 @@
 
 	sess->pend_pos = p;
 	p->sess = sess;
-	p->srv  = sess->srv;
+	p->srv = srv = target_srv(&sess->target);
 
-	if (sess->flags & SN_ASSIGNED && sess->srv) {
-		LIST_ADDQ(&sess->srv->pendconns, &p->list);
-		sess->srv->nbpend++;
-		sess->logs.srv_queue_size += sess->srv->nbpend;
-		if (sess->srv->nbpend > sess->srv->counters.nbpend_max)
-			sess->srv->counters.nbpend_max = sess->srv->nbpend;
+	if (sess->flags & SN_ASSIGNED && srv) {
+		LIST_ADDQ(&srv->pendconns, &p->list);
+		srv->nbpend++;
+		sess->logs.srv_queue_size += srv->nbpend;
+		if (srv->nbpend > srv->counters.nbpend_max)
+			srv->counters.nbpend_max = srv->nbpend;
 	} else {
 		LIST_ADDQ(&sess->be->pendconns, &p->list);
 		sess->be->nbpend++;
diff --git a/src/session.c b/src/session.c
index 864b788..5cd0853 100644
--- a/src/session.c
+++ b/src/session.c
@@ -200,7 +200,7 @@
 	if (likely(s->fe->options2 & PR_O2_INDEPSTR))
 		s->si[1].flags |= SI_FL_INDEP_STR;
 
-	s->srv = s->srv_conn = NULL;
+	s->srv_conn = NULL;
 	clear_target(&s->target);
 	s->pend_pos = NULL;
 
@@ -324,13 +324,13 @@
 	if (s->pend_pos)
 		pendconn_free(s->pend_pos);
 
-	if (s->srv) { /* there may be requests left pending in queue */
+	if (target_srv(&s->target)) { /* there may be requests left pending in queue */
 		if (s->flags & SN_CURR_SESS) {
 			s->flags &= ~SN_CURR_SESS;
-			s->srv->cur_sess--;
+			target_srv(&s->target)->cur_sess--;
 		}
-		if (may_dequeue_tasks(s->srv, s->be))
-			process_srv_queue(s->srv);
+		if (may_dequeue_tasks(target_srv(&s->target), s->be))
+			process_srv_queue(target_srv(&s->target));
 	}
 
 	if (unlikely(s->srv_conn)) {
@@ -415,8 +415,8 @@
 			if (s->be != s->fe)
 				s->be->counters.bytes_in		+= bytes;
 
-			if (s->srv)
-				s->srv->counters.bytes_in		+= bytes;
+			if (target_srv(&s->target))
+				target_srv(&s->target)->counters.bytes_in		+= bytes;
 
 			if (s->listener->counters)
 				s->listener->counters->bytes_in		+= bytes;
@@ -466,8 +466,8 @@
 			if (s->be != s->fe)
 				s->be->counters.bytes_out		+= bytes;
 
-			if (s->srv)
-				s->srv->counters.bytes_out		+= bytes;
+			if (target_srv(&s->target))
+				target_srv(&s->target)->counters.bytes_out		+= bytes;
 
 			if (s->listener->counters)
 				s->listener->counters->bytes_out	+= bytes;
@@ -537,7 +537,7 @@
 		if (si->err_type)
 			return 0;
 
-		si->err_loc = s->srv;
+		si->err_loc = target_srv(&s->target);
 		if (si->flags & SI_FL_ERR)
 			si->err_type = SI_ET_CONN_ERR;
 		else
@@ -553,7 +553,7 @@
 		/* give up */
 		si->shutw(si);
 		si->err_type |= SI_ET_CONN_ABRT;
-		si->err_loc  = s->srv;
+		si->err_loc  = target_srv(&s->target);
 		si->flags &= ~SI_FL_CAP_SPLICE;
 		if (s->srv_error)
 			s->srv_error(s, si);
@@ -587,12 +587,12 @@
 int sess_update_st_cer(struct session *s, struct stream_interface *si)
 {
 	/* we probably have to release last session from the server */
-	if (s->srv) {
-		health_adjust(s->srv, HANA_STATUS_L4_ERR);
+	if (target_srv(&s->target)) {
+		health_adjust(target_srv(&s->target), HANA_STATUS_L4_ERR);
 
 		if (s->flags & SN_CURR_SESS) {
 			s->flags &= ~SN_CURR_SESS;
-			s->srv->cur_sess--;
+			target_srv(&s->target)->cur_sess--;
 		}
 	}
 
@@ -601,15 +601,15 @@
 	if (si->conn_retries < 0) {
 		if (!si->err_type) {
 			si->err_type = SI_ET_CONN_ERR;
-			si->err_loc = s->srv;
+			si->err_loc = target_srv(&s->target);
 		}
 
-		if (s->srv)
-			s->srv->counters.failed_conns++;
+		if (target_srv(&s->target))
+			target_srv(&s->target)->counters.failed_conns++;
 		s->be->counters.failed_conns++;
 		sess_change_server(s, NULL);
-		if (may_dequeue_tasks(s->srv, s->be))
-			process_srv_queue(s->srv);
+		if (may_dequeue_tasks(target_srv(&s->target), s->be))
+			process_srv_queue(target_srv(&s->target));
 
 		/* shutw is enough so stop a connecting socket */
 		si->shutw(si);
@@ -628,17 +628,17 @@
 	 * bit to ignore any persistence cookie. We won't count a retry nor a
 	 * redispatch yet, because this will depend on what server is selected.
 	 */
-	if (s->srv && si->conn_retries == 0 &&
+	if (target_srv(&s->target) && si->conn_retries == 0 &&
 	    s->be->options & PR_O_REDISP && !(s->flags & SN_FORCE_PRST)) {
 		sess_change_server(s, NULL);
-		if (may_dequeue_tasks(s->srv, s->be))
-			process_srv_queue(s->srv);
+		if (may_dequeue_tasks(target_srv(&s->target), s->be))
+			process_srv_queue(target_srv(&s->target));
 
 		s->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
 		si->state = SI_ST_REQ;
 	} else {
-		if (s->srv)
-			s->srv->counters.retries++;
+		if (target_srv(&s->target))
+			target_srv(&s->target)->counters.retries++;
 		s->be->counters.retries++;
 		si->state = SI_ST_ASS;
 	}
@@ -670,8 +670,8 @@
 	struct buffer *req = si->ob;
 	struct buffer *rep = si->ib;
 
-	if (s->srv)
-		health_adjust(s->srv, HANA_STATUS_L4_OK);
+	if (target_srv(&s->target))
+		health_adjust(target_srv(&s->target), HANA_STATUS_L4_OK);
 
 	if (s->be->mode == PR_MODE_TCP) { /* let's allow immediate data connection in this case */
 		/* if the user wants to log as soon as possible, without counting
@@ -706,6 +706,8 @@
  */
 void sess_update_stream_int(struct session *s, struct stream_interface *si)
 {
+	struct server *srv = target_srv(&s->target);
+
 	DPRINTF(stderr,"[%u] %s: sess=%p rq=%p, rp=%p, exp(r,w)=%u,%u rqf=%08x rpf=%08x rql=%d rpl=%d cs=%d ss=%d\n",
 		now_ms, __FUNCTION__,
 		s,
@@ -719,10 +721,12 @@
 		int conn_err;
 
 		conn_err = connect_server(s);
+		srv = target_srv(&s->target);
+
 		if (conn_err == SN_ERR_NONE) {
 			/* state = SI_ST_CON now */
-			if (s->srv)
-				srv_inc_sess_ctr(s->srv);
+			if (srv)
+				srv_inc_sess_ctr(srv);
 			return;
 		}
 
@@ -732,19 +736,19 @@
 		if (conn_err == SN_ERR_INTERNAL) {
 			if (!si->err_type) {
 				si->err_type = SI_ET_CONN_OTHER;
-				si->err_loc  = s->srv;
+				si->err_loc  = srv;
 			}
 
-			if (s->srv)
-				srv_inc_sess_ctr(s->srv);
-			if (s->srv)
-				s->srv->counters.failed_conns++;
+			if (srv)
+				srv_inc_sess_ctr(srv);
+			if (srv)
+				srv->counters.failed_conns++;
 			s->be->counters.failed_conns++;
 
 			/* release other sessions waiting for this server */
 			sess_change_server(s, NULL);
-			if (may_dequeue_tasks(s->srv, s->be))
-				process_srv_queue(s->srv);
+			if (may_dequeue_tasks(srv, s->be))
+				process_srv_queue(srv);
 
 			/* Failed and not retryable. */
 			si->shutr(si);
@@ -793,8 +797,8 @@
 			/* ... and timeout expired */
 			si->exp = TICK_ETERNITY;
 			s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
-			if (s->srv)
-				s->srv->counters.failed_conns++;
+			if (srv)
+				srv->counters.failed_conns++;
 			s->be->counters.failed_conns++;
 			si->shutr(si);
 			si->shutw(si);
@@ -1063,7 +1067,6 @@
 							    (px->options & PR_O_PERSIST) ||
 							    (s->flags & SN_FORCE_PRST)) {
 								s->flags |= SN_DIRECT | SN_ASSIGNED;
-								s->srv = srv;
 								set_target_server(&s->target, srv);
 							}
 						}
@@ -1171,7 +1174,7 @@
 
 		s->store[i].ts = NULL;
 		ptr = stktable_data_ptr(s->store[i].table, ts, STKTABLE_DT_SERVER_ID);
-		stktable_data_cast(ptr, server_id) = s->srv->puid;
+		stktable_data_cast(ptr, server_id) = target_srv(&s->target)->puid;
 	}
 	s->store_count = 0; /* everything is stored */
 
@@ -1202,6 +1205,7 @@
  */
 struct task *process_session(struct task *t)
 {
+	struct server *srv;
 	struct session *s = t->context;
 	unsigned int rqf_last, rpf_last;
 	unsigned int rq_prod_last, rq_cons_last;
@@ -1268,6 +1272,7 @@
 	 * the client cannot have connect (hence retryable) errors. Also, the
 	 * connection setup code must be able to deal with any type of abort.
 	 */
+	srv = target_srv(&s->target);
 	if (unlikely(s->si[0].flags & SI_FL_ERR)) {
 		if (s->si[0].state == SI_ST_EST || s->si[0].state == SI_ST_DIS) {
 			s->si[0].shutr(&s->si[0]);
@@ -1275,8 +1280,8 @@
 			stream_int_report_error(&s->si[0]);
 			if (!(s->req->analysers) && !(s->rep->analysers)) {
 				s->be->counters.cli_aborts++;
-				if (s->srv)
-					s->srv->counters.cli_aborts++;
+				if (srv)
+					srv->counters.cli_aborts++;
 				if (!(s->flags & SN_ERR_MASK))
 					s->flags |= SN_ERR_CLICL;
 				if (!(s->flags & SN_FINST_MASK))
@@ -1291,12 +1296,12 @@
 			s->si[1].shutw(&s->si[1]);
 			stream_int_report_error(&s->si[1]);
 			s->be->counters.failed_resp++;
-			if (s->srv)
-				s->srv->counters.failed_resp++;
+			if (srv)
+				srv->counters.failed_resp++;
 			if (!(s->req->analysers) && !(s->rep->analysers)) {
 				s->be->counters.srv_aborts++;
-				if (s->srv)
-					s->srv->counters.srv_aborts++;
+				if (srv)
+					srv->counters.srv_aborts++;
 				if (!(s->flags & SN_ERR_MASK))
 					s->flags |= SN_ERR_SRVCL;
 				if (!(s->flags & SN_FINST_MASK))
@@ -1350,14 +1355,15 @@
 	 */
 	if (unlikely(s->req->cons->state == SI_ST_DIS)) {
 		s->req->cons->state = SI_ST_CLO;
-		if (s->srv) {
+		srv = target_srv(&s->target);
+		if (srv) {
 			if (s->flags & SN_CURR_SESS) {
 				s->flags &= ~SN_CURR_SESS;
-				s->srv->cur_sess--;
+				srv->cur_sess--;
 			}
 			sess_change_server(s, NULL);
-			if (may_dequeue_tasks(s->srv, s->be))
-				process_srv_queue(s->srv);
+			if (may_dequeue_tasks(srv, s->be))
+				process_srv_queue(srv);
 		}
 	}
 
@@ -1647,32 +1653,33 @@
 	 * we're just in a data phase here since it means we have not
 	 * seen any analyser who could set an error status.
 	 */
+	srv = target_srv(&s->target);
 	if (unlikely(!(s->flags & SN_ERR_MASK))) {
 		if (s->req->flags & (BF_READ_ERROR|BF_READ_TIMEOUT|BF_WRITE_ERROR|BF_WRITE_TIMEOUT)) {
 			/* Report it if the client got an error or a read timeout expired */
 			s->req->analysers = 0;
 			if (s->req->flags & BF_READ_ERROR) {
 				s->be->counters.cli_aborts++;
-				if (s->srv)
-					s->srv->counters.cli_aborts++;
+				if (srv)
+					srv->counters.cli_aborts++;
 				s->flags |= SN_ERR_CLICL;
 			}
 			else if (s->req->flags & BF_READ_TIMEOUT) {
 				s->be->counters.cli_aborts++;
-				if (s->srv)
-					s->srv->counters.cli_aborts++;
+				if (srv)
+					srv->counters.cli_aborts++;
 				s->flags |= SN_ERR_CLITO;
 			}
 			else if (s->req->flags & BF_WRITE_ERROR) {
 				s->be->counters.srv_aborts++;
-				if (s->srv)
-					s->srv->counters.srv_aborts++;
+				if (srv)
+					srv->counters.srv_aborts++;
 				s->flags |= SN_ERR_SRVCL;
 			}
 			else {
 				s->be->counters.srv_aborts++;
-				if (s->srv)
-					s->srv->counters.srv_aborts++;
+				if (srv)
+					srv->counters.srv_aborts++;
 				s->flags |= SN_ERR_SRVTO;
 			}
 			sess_set_term_flags(s);
@@ -1682,26 +1689,26 @@
 			s->rep->analysers = 0;
 			if (s->rep->flags & BF_READ_ERROR) {
 				s->be->counters.srv_aborts++;
-				if (s->srv)
-					s->srv->counters.srv_aborts++;
+				if (srv)
+					srv->counters.srv_aborts++;
 				s->flags |= SN_ERR_SRVCL;
 			}
 			else if (s->rep->flags & BF_READ_TIMEOUT) {
 				s->be->counters.srv_aborts++;
-				if (s->srv)
-					s->srv->counters.srv_aborts++;
+				if (srv)
+					srv->counters.srv_aborts++;
 				s->flags |= SN_ERR_SRVTO;
 			}
 			else if (s->rep->flags & BF_WRITE_ERROR) {
 				s->be->counters.cli_aborts++;
-				if (s->srv)
-					s->srv->counters.cli_aborts++;
+				if (srv)
+					srv->counters.cli_aborts++;
 				s->flags |= SN_ERR_CLICL;
 			}
 			else {
 				s->be->counters.cli_aborts++;
-				if (s->srv)
-					s->srv->counters.cli_aborts++;
+				if (srv)
+					srv->counters.cli_aborts++;
 				s->flags |= SN_ERR_CLITO;
 			}
 			sess_set_term_flags(s);
@@ -1821,8 +1828,8 @@
 			if (s->si[1].state == SI_ST_REQ)
 				sess_prepare_conn_req(s, &s->si[1]);
 
-			if (s->si[1].state == SI_ST_ASS && s->srv &&
-			    s->srv->rdr_len && (s->flags & SN_REDIRECTABLE))
+			srv = target_srv(&s->target);
+			if (s->si[1].state == SI_ST_ASS && srv && srv->rdr_len && (s->flags & SN_REDIRECTABLE))
 				perform_http_redirect(s, &s->si[1]);
 		} while (s->si[1].state == SI_ST_ASS);
 	}