From 505e34a36d40a131c4d5cd8f63eac90dd305c8cb Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Fri, 6 Jul 2012 10:17:53 +0200 Subject: [PATCH] MAJOR: get rid of fdtab[].state and use connection->flags instead fdtab[].state was only used to know whether a connection was in progress or an error was encountered. Instead we now use connection->flags to store a flag for both. This way, connection management will be able to update the connection status on I/O. --- include/types/fd.h | 6 ------ src/checks.c | 11 +++++------ src/peers.c | 2 ++ src/proto_http.c | 1 + src/proto_tcp.c | 17 ++++++++--------- src/proto_uxst.c | 1 - src/session.c | 3 ++- src/sock_raw.c | 18 +++++++++--------- 8 files changed, 27 insertions(+), 32 deletions(-) diff --git a/include/types/fd.h b/include/types/fd.h index 5d5c5ed8e..3b009942c 100644 --- a/include/types/fd.h +++ b/include/types/fd.h @@ -31,11 +31,6 @@ #include #include -/* different possible states for the fd */ -#define FD_STCONN 2 -#define FD_STREADY 3 -#define FD_STERROR 4 - enum { DIR_RD=0, DIR_WR=1, @@ -74,7 +69,6 @@ struct fdtab { unsigned int s1; /* Position in spec list+1. 0=not in list. */ } spec; unsigned short flags; /* various flags precising the exact status of this fd */ - unsigned char state; /* the state of this fd */ unsigned char ev; /* event seen in return of poll() : FD_POLL_* */ }; diff --git a/src/checks.c b/src/checks.c index 3bf5ec6ed..2c2ee7ef7 100644 --- a/src/checks.c +++ b/src/checks.c @@ -772,8 +772,7 @@ static int event_srv_chk_w(int fd) struct task *t = fdtab[fd].owner; struct server *s = t->context; - //fprintf(stderr, "event_srv_chk_w, state=%ld\n", unlikely(fdtab[fd].state)); - if (unlikely(fdtab[fd].state == FD_STERROR || (fdtab[fd].ev & FD_POLL_ERR))) { + if (unlikely((s->check_conn->flags & CO_FL_ERROR) || (fdtab[fd].ev & FD_POLL_ERR))) { int skerr, err = errno; socklen_t lskerr = sizeof(skerr); @@ -888,7 +887,7 @@ static int event_srv_chk_w(int fd) fdtab[fd].ev &= ~FD_POLL_OUT; return 0; out_error: - fdtab[fd].state = FD_STERROR; + s->check_conn->flags |= CO_FL_ERROR; goto out_wakeup; } @@ -920,7 +919,7 @@ static int event_srv_chk_r(int fd) int done; unsigned short msglen; - if (unlikely((s->result & SRV_CHK_ERROR) || (fdtab[fd].state == FD_STERROR))) { + if (unlikely((s->result & SRV_CHK_ERROR) || (s->check_conn->flags & CO_FL_ERROR))) { /* in case of TCP only, this tells us if the connection failed */ if (!(s->result & SRV_CHK_ERROR)) set_server_check_status(s, HCHK_STATUS_SOCKERR, NULL); @@ -1232,7 +1231,7 @@ static int event_srv_chk_r(int fd) out_wakeup: if (s->result & SRV_CHK_ERROR) - fdtab[fd].state = FD_STERROR; + s->check_conn->flags |= CO_FL_ERROR; /* Reset the check buffer... */ *s->check_data = '\0'; @@ -1461,11 +1460,11 @@ static struct task *process_chk(struct task *t) //fprintf(stderr, "process_chk: 4\n"); s->curfd = fd; /* that's how we know a test is in progress ;-) */ + s->check_conn->flags = CO_FL_WAIT_L4_CONN; /* TCP connection pending */ fd_insert(fd); fdtab[fd].owner = t; fdtab[fd].cb[DIR_RD].f = &event_srv_chk_r; fdtab[fd].cb[DIR_WR].f = &event_srv_chk_w; - 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 */ #ifdef DEBUG_FULL diff --git a/src/peers.c b/src/peers.c index c12dcf6f1..e18b06526 100644 --- a/src/peers.c +++ b/src/peers.c @@ -1152,6 +1152,7 @@ static struct session *peer_session_create(struct peer *peer, struct peer_sessio s->si[0].conn.peeraddr = NULL; s->si[0].conn.peerlen = 0; s->si[0].conn.t.sock.fd = -1; + s->si[0].conn.flags = CO_FL_NONE; s->si[0].owner = t; s->si[0].state = s->si[0].prev_state = SI_ST_EST; s->si[0].err_type = SI_ET_NONE; @@ -1172,6 +1173,7 @@ static struct session *peer_session_create(struct peer *peer, struct peer_sessio s->si[1].conn.peeraddr = NULL; s->si[1].conn.peerlen = 0; s->si[1].conn.t.sock.fd = -1; /* just to help with debugging */ + s->si[1].conn.flags = CO_FL_NONE; s->si[1].owner = t; s->si[1].state = s->si[1].prev_state = SI_ST_ASS; s->si[1].conn_retries = p->conn_retries; diff --git a/src/proto_http.c b/src/proto_http.c index 4a02f9160..08e2c9d80 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -3823,6 +3823,7 @@ void http_end_txn_clean_session(struct session *s) s->req->cons->state = s->req->cons->prev_state = SI_ST_INI; s->req->cons->conn.t.sock.fd = -1; /* just to help with debugging */ + s->req->cons->conn.flags = CO_FL_NONE; s->req->cons->err_type = SI_ET_NONE; s->req->cons->conn_retries = 0; /* used for logging too */ s->req->cons->err_loc = NULL; diff --git a/src/proto_tcp.c b/src/proto_tcp.c index 7da152a0d..ddc8269e0 100644 --- a/src/proto_tcp.c +++ b/src/proto_tcp.c @@ -466,8 +466,8 @@ int tcp_connect_server(struct stream_interface *si) si_get_from_addr(si); fdtab[fd].owner = si; - fdtab[fd].state = FD_STCONN; /* connection in progress */ fdtab[fd].flags = FD_FL_TCP | FD_FL_TCP_NODELAY; + si->conn.flags = CO_FL_WAIT_L4_CONN; /* connection in progress */ /* If we have nothing to send, we want to confirm that the TCP * connection is established before doing so, so we use our own write @@ -538,10 +538,10 @@ static int tcp_connect_write(int fd) struct buffer *b = si->ob; int retval = 0; - if (fdtab[fd].state == FD_STERROR) + if (si->conn.flags & CO_FL_ERROR) goto out_error; - if (fdtab[fd].state != FD_STCONN) + if (!(si->conn.flags & CO_FL_WAIT_L4_CONN)) goto out_ignore; /* strange we were called while ready */ /* we might have been called just after an asynchronous shutw */ @@ -618,7 +618,7 @@ static int tcp_connect_write(int fd) */ fdtab[fd].cb[DIR_RD].f = si_data(si)->read; fdtab[fd].cb[DIR_WR].f = si_data(si)->write; - fdtab[fd].state = FD_STREADY; + si->conn.flags &= ~CO_FL_WAIT_L4_CONN; si->exp = TICK_ETERNITY; return si_data(si)->write(fd); @@ -637,7 +637,7 @@ static int tcp_connect_write(int fd) * connection retries. */ - fdtab[fd].state = FD_STERROR; + si->conn.flags |= CO_FL_ERROR; fdtab[fd].ev &= ~FD_POLL_STICKY; EV_FD_REM(fd); si->flags |= SI_FL_ERR; @@ -654,10 +654,10 @@ static int tcp_connect_read(int fd) retval = 1; - if (fdtab[fd].state == FD_STERROR) + if (si->conn.flags & CO_FL_ERROR) goto out_error; - if (fdtab[fd].state != FD_STCONN) { + if (!(si->conn.flags & CO_FL_WAIT_L4_CONN)) { retval = 0; goto out_ignore; /* strange we were called while ready */ } @@ -680,7 +680,7 @@ static int tcp_connect_read(int fd) * connection retries. */ - fdtab[fd].state = FD_STERROR; + si->conn.flags |= CO_FL_ERROR; fdtab[fd].ev &= ~FD_POLL_STICKY; EV_FD_REM(fd); si->flags |= SI_FL_ERR; @@ -818,7 +818,6 @@ int tcp_bind_listener(struct listener *listener, char *errmsg, int errlen) listener->state = LI_LISTEN; fdtab[fd].owner = listener; /* reference the listener instead of a task */ - fdtab[fd].state = 0; /* anything will do, but avoid FD_STERROR */ fdtab[fd].flags = FD_FL_TCP | ((listener->options & LI_O_NOLINGER) ? FD_FL_TCP_NOLING : 0); fdtab[fd].cb[DIR_RD].f = listener->proto->accept; fdtab[fd].cb[DIR_WR].f = NULL; /* never called */ diff --git a/src/proto_uxst.c b/src/proto_uxst.c index 35e48fd06..f63760183 100644 --- a/src/proto_uxst.c +++ b/src/proto_uxst.c @@ -265,7 +265,6 @@ static int uxst_bind_listener(struct listener *listener, char *errmsg, int errle fdtab[fd].cb[DIR_RD].f = listener->proto->accept; fdtab[fd].cb[DIR_WR].f = NULL; /* never called */ fdtab[fd].owner = listener; /* reference the listener instead of a task */ - fdtab[fd].state = 0; /* anything will do, but avoid FD_STERROR */ return ERR_NONE; err_rename: ret = rename(backname, path); diff --git a/src/session.c b/src/session.c index e839922e3..c67d85ec3 100644 --- a/src/session.c +++ b/src/session.c @@ -86,6 +86,7 @@ int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr) s->term_trace = 0; s->si[0].conn.t.sock.fd = cfd; s->si[0].conn.ctrl = l->proto; + s->si[0].conn.flags = CO_FL_NONE; s->si[0].addr.from = *addr; s->si[0].conn.peeraddr = (struct sockaddr *)&s->si[0].addr.from; s->si[0].conn.peerlen = sizeof(s->si[0].addr.from); @@ -188,6 +189,7 @@ int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr) * callbacks will be initialized before attempting to connect. */ s->si[1].conn.t.sock.fd = -1; /* just to help with debugging */ + s->si[1].conn.flags = CO_FL_NONE; s->si[1].owner = t; s->si[1].state = s->si[1].prev_state = SI_ST_INI; s->si[1].err_type = SI_ET_NONE; @@ -279,7 +281,6 @@ int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr) /* finish initialization of the accepted file descriptor */ fd_insert(cfd); fdtab[cfd].owner = &s->si[0]; - fdtab[cfd].state = FD_STREADY; fdtab[cfd].flags = 0; fdtab[cfd].cb[DIR_RD].f = si_data(&s->si[0])->read; fdtab[cfd].cb[DIR_WR].f = si_data(&s->si[0])->write; diff --git a/src/sock_raw.c b/src/sock_raw.c index 376cd7c80..c561a5510 100644 --- a/src/sock_raw.c +++ b/src/sock_raw.c @@ -245,7 +245,7 @@ static int sock_raw_read(int fd) * happens when we send too large a request to a backend server * which rejects it before reading it all. */ - if (fdtab[fd].state == FD_STERROR) + if (si->conn.flags & CO_FL_ERROR) goto out_error; /* stop here if we reached the end of data */ @@ -323,8 +323,8 @@ static int sock_raw_read(int fd) b_adv(b, fwd); } - if (fdtab[fd].state == FD_STCONN) { - fdtab[fd].state = FD_STREADY; + if (si->conn.flags & CO_FL_WAIT_L4_CONN) { + si->conn.flags &= ~CO_FL_WAIT_L4_CONN; si->exp = TICK_ETERNITY; } @@ -503,7 +503,7 @@ static int sock_raw_read(int fd) * connection retries. */ - fdtab[fd].state = FD_STERROR; + si->conn.flags |= CO_FL_ERROR; fdtab[fd].ev &= ~FD_POLL_STICKY; EV_FD_REM(fd); si->flags |= SI_FL_ERR; @@ -614,8 +614,8 @@ static int sock_raw_write_loop(struct stream_interface *si, struct buffer *b) } if (ret > 0) { - if (fdtab[si_fd(si)].state == FD_STCONN) { - fdtab[si_fd(si)].state = FD_STREADY; + if (si->conn.flags & CO_FL_WAIT_L4_CONN) { + si->conn.flags &= ~CO_FL_WAIT_L4_CONN; si->exp = TICK_ETERNITY; } @@ -676,7 +676,7 @@ static int sock_raw_write(int fd) #endif retval = 1; - if (fdtab[fd].state == FD_STERROR) + if (si->conn.flags & CO_FL_ERROR) goto out_error; /* we might have been called just after an asynchronous shutw */ @@ -750,7 +750,7 @@ static int sock_raw_write(int fd) * connection retries. */ - fdtab[fd].state = FD_STERROR; + si->conn.flags |= CO_FL_ERROR; fdtab[fd].ev &= ~FD_POLL_STICKY; EV_FD_REM(fd); si->flags |= SI_FL_ERR; @@ -1013,7 +1013,7 @@ static void sock_raw_chk_snd(struct stream_interface *si) /* Write error on the file descriptor. We mark the FD as STERROR so * that we don't use it anymore and we notify the task. */ - fdtab[si_fd(si)].state = FD_STERROR; + si->conn.flags |= CO_FL_ERROR; fdtab[si_fd(si)].ev &= ~FD_POLL_STICKY; EV_FD_REM(si_fd(si)); si->flags |= SI_FL_ERR;