[OPTIM] move some rarely used fields out of fdtab

Some rarely information are stored in fdtab, making it larger for no
reason (source port ranges, remote address, ...). Such information
lie there because the checks can't find them anywhere else. The goal
will be to move these information to the stream interface once the
checks make use of it.

For now, we move them to an fdinfo array. This simple change might
have improved the cache hit ratio a little bit because a 0.5% of
performance increase has measured.
diff --git a/src/checks.c b/src/checks.c
index 0e9aca5..e7aefb4 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -838,19 +838,19 @@
 							/* note: in case of retry, we may have to release a previously
 							 * allocated port, hence this loop's construct.
 							 */
-							port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
-							fdtab[fd].port_range = NULL;
+							port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
+							fdinfo[fd].port_range = NULL;
 
 							if (!bind_attempts)
 								break;
 							bind_attempts--;
 
-							fdtab[fd].local_port = port_range_alloc_port(s->sport_range);
-							if (!fdtab[fd].local_port)
+							fdinfo[fd].local_port = port_range_alloc_port(s->sport_range);
+							if (!fdinfo[fd].local_port)
 								break;
 
-							fdtab[fd].port_range = s->sport_range;
-							src.sin_port = htons(fdtab[fd].local_port);
+							fdinfo[fd].port_range = s->sport_range;
+							src.sin_port = htons(fdinfo[fd].local_port);
 
 							ret = tcpv4_bind_socket(fd, flags, &src, remote);
 						} while (ret != 0); /* binding NOK */
@@ -926,8 +926,8 @@
 						fdtab[fd].cb[DIR_RD].b = NULL;
 						fdtab[fd].cb[DIR_WR].f = &event_srv_chk_w;
 						fdtab[fd].cb[DIR_WR].b = NULL;
-						fdtab[fd].peeraddr = (struct sockaddr *)&sa;
-						fdtab[fd].peerlen = sizeof(sa);
+						fdinfo[fd].peeraddr = (struct sockaddr *)&sa;
+						fdinfo[fd].peerlen = sizeof(sa);
 						fdtab[fd].state = FD_STCONN; /* connection in progress */
 						fdtab[fd].flags = FD_FL_TCP | FD_FL_TCP_NODELAY;
 						EV_FD_SET(fd, DIR_WR);  /* for connect status */
@@ -963,8 +963,8 @@
 					}
 				}
 			}
-			port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
-			fdtab[fd].port_range = NULL;
+			port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
+			fdinfo[fd].port_range = NULL;
 			close(fd); /* socket creation error */
 		}
 
diff --git a/src/client.c b/src/client.c
index b9e304a..68a192d 100644
--- a/src/client.c
+++ b/src/client.c
@@ -449,8 +449,8 @@
 		fdtab[cfd].cb[DIR_RD].b = s->req;
 		fdtab[cfd].cb[DIR_WR].f = l->proto->write;
 		fdtab[cfd].cb[DIR_WR].b = s->rep;
-		fdtab[cfd].peeraddr = (struct sockaddr *)&s->cli_addr;
-		fdtab[cfd].peerlen = sizeof(s->cli_addr);
+		fdinfo[cfd].peeraddr = (struct sockaddr *)&s->cli_addr;
+		fdinfo[cfd].peerlen = sizeof(s->cli_addr);
 
 		if ((p->mode == PR_MODE_HTTP && (s->flags & SN_MONITOR)) ||
 		    (p->mode == PR_MODE_HEALTH && (p->options & PR_O_HTTP_CHK))) {
diff --git a/src/fd.c b/src/fd.c
index 9dd365a..c850efa 100644
--- a/src/fd.c
+++ b/src/fd.c
@@ -22,6 +22,7 @@
 #include <proto/port_range.h>
 
 struct fdtab *fdtab = NULL;     /* array of all the file descriptors */
+struct fdinfo *fdinfo = NULL;   /* less-often used infos for file descriptors */
 int maxfd;                      /* # of the highest fd + 1 */
 int totalconn;                  /* total # of terminated sessions */
 int actconn;                    /* # of active sessions */
@@ -37,8 +38,8 @@
 void fd_delete(int fd)
 {
 	EV_FD_CLO(fd);
-	port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
-	fdtab[fd].port_range = NULL;
+	port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
+	fdinfo[fd].port_range = NULL;
 	close(fd);
 	fdtab[fd].state = FD_STCLOSE;
 
diff --git a/src/haproxy.c b/src/haproxy.c
index 83df092..43aee22 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -641,6 +641,8 @@
 	if (global.nbproc < 1)
 		global.nbproc = 1;
 
+	fdinfo = (struct fdinfo *)calloc(1,
+				       sizeof(struct fdinfo) * (global.maxsock));
 	fdtab = (struct fdtab *)calloc(1,
 				       sizeof(struct fdtab) * (global.maxsock));
 	for (i = 0; i < global.maxsock; i++) {
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index 884016f..68da063 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -279,19 +279,19 @@
 				/* note: in case of retry, we may have to release a previously
 				 * allocated port, hence this loop's construct.
 				 */
-				port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
-				fdtab[fd].port_range = NULL;
+				port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
+				fdinfo[fd].port_range = NULL;
 
 				if (!attempts)
 					break;
 				attempts--;
 
-				fdtab[fd].local_port = port_range_alloc_port(srv->sport_range);
-				if (!fdtab[fd].local_port)
+				fdinfo[fd].local_port = port_range_alloc_port(srv->sport_range);
+				if (!fdinfo[fd].local_port)
 					break;
 
-				fdtab[fd].port_range = srv->sport_range;
-				src.sin_port = htons(fdtab[fd].local_port);
+				fdinfo[fd].port_range = srv->sport_range;
+				src.sin_port = htons(fdinfo[fd].local_port);
 
 				ret = tcpv4_bind_socket(fd, flags, &src, remote);
 			} while (ret != 0); /* binding NOK */
@@ -301,8 +301,8 @@
 		}
 
 		if (ret) {
-			port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
-			fdtab[fd].port_range = NULL;
+			port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
+			fdinfo[fd].port_range = NULL;
 			close(fd);
 
 			if (ret == 1) {
@@ -388,8 +388,8 @@
 				msg = "local address already in use";
 
 			qfprintf(stderr,"Cannot connect: %s.\n",msg);
-			port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
-			fdtab[fd].port_range = NULL;
+			port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
+			fdinfo[fd].port_range = NULL;
 			close(fd);
 			send_log(be, LOG_EMERG,
 				 "Connect() failed for server %s/%s: %s.\n",
@@ -397,15 +397,15 @@
 			return SN_ERR_RESOURCE;
 		} else if (errno == ETIMEDOUT) {
 			//qfprintf(stderr,"Connect(): ETIMEDOUT");
-			port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
-			fdtab[fd].port_range = NULL;
+			port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
+			fdinfo[fd].port_range = NULL;
 			close(fd);
 			return SN_ERR_SRVTO;
 		} else {
 			// (errno == ECONNREFUSED || errno == ENETUNREACH || errno == EACCES || errno == EPERM)
 			//qfprintf(stderr,"Connect(): %d", errno);
-			port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
-			fdtab[fd].port_range = NULL;
+			port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
+			fdinfo[fd].port_range = NULL;
 			close(fd);
 			return SN_ERR_SRVCL;
 		}
@@ -419,8 +419,8 @@
 	fdtab[fd].cb[DIR_WR].f = &stream_sock_write;
 	fdtab[fd].cb[DIR_WR].b = si->ob;
 
-	fdtab[fd].peeraddr = (struct sockaddr *)srv_addr;
-	fdtab[fd].peerlen = sizeof(struct sockaddr_in);
+	fdinfo[fd].peeraddr = (struct sockaddr *)srv_addr;
+	fdinfo[fd].peerlen = sizeof(struct sockaddr_in);
 
 	fd_insert(fd);
 	EV_FD_SET(fd, DIR_WR);  /* for connect status */
@@ -562,8 +562,8 @@
 	if (listener->options & LI_O_NOLINGER)
 		fdtab[fd].flags |= FD_FL_TCP_NOLING;
 
-	fdtab[fd].peeraddr = NULL;
-	fdtab[fd].peerlen = 0;
+	fdinfo[fd].peeraddr = NULL;
+	fdinfo[fd].peerlen = 0;
  tcp_return:
 	if (msg && errlen)
 		strlcpy2(errmsg, msg, errlen);
diff --git a/src/proto_uxst.c b/src/proto_uxst.c
index 4fceadc..186ddda 100644
--- a/src/proto_uxst.c
+++ b/src/proto_uxst.c
@@ -267,8 +267,8 @@
 	fdtab[fd].cb[DIR_RD].b = fdtab[fd].cb[DIR_WR].b = NULL;
 	fdtab[fd].owner = listener; /* reference the listener instead of a task */
 	fdtab[fd].state = FD_STLISTEN;
-	fdtab[fd].peeraddr = NULL;
-	fdtab[fd].peerlen = 0;
+	fdinfo[fd].peeraddr = NULL;
+	fdinfo[fd].peerlen = 0;
 	return ERR_NONE;
 }
 
@@ -537,8 +537,8 @@
 		fdtab[cfd].cb[DIR_RD].b = s->req;
 		fdtab[cfd].cb[DIR_WR].f = l->proto->write;
 		fdtab[cfd].cb[DIR_WR].b = s->rep;
-		fdtab[cfd].peeraddr = (struct sockaddr *)&s->cli_addr;
-		fdtab[cfd].peerlen = sizeof(s->cli_addr);
+		fdinfo[cfd].peeraddr = (struct sockaddr *)&s->cli_addr;
+		fdinfo[cfd].peerlen = sizeof(s->cli_addr);
 
 		EV_FD_SET(cfd, DIR_RD);
 
diff --git a/src/stream_sock.c b/src/stream_sock.c
index 2846b36..65b790a 100644
--- a/src/stream_sock.c
+++ b/src/stream_sock.c
@@ -712,7 +712,7 @@
 			 *  - connecting (EALREADY, EINPROGRESS)
 			 *  - connected (EISCONN, 0)
 			 */
-			if ((connect(fd, fdtab[fd].peeraddr, fdtab[fd].peerlen) == 0))
+			if ((connect(fd, fdinfo[fd].peeraddr, fdinfo[fd].peerlen) == 0))
 				errno = 0;
 
 			if (errno == EALREADY || errno == EINPROGRESS) {