Browse code

tcp: async write timeout fixes

- fixed a wrong write timeout test on connection-read-release
(TICKS_LE instead of TICKS_GE)

- fixed initial write timeout after connection creation (the
timeout was ended up set to tcp_con_lifetime instead of
tcp_wq_timeout)

Andrei Pelinescu-Onciul authored on 26/02/2009 23:13:44
Showing 1 changed files
... ...
@@ -2661,7 +2661,7 @@ inline static int handle_tcp_child(struct tcp_child* tcp_c, int fd_i)
2661 2661
 #ifdef TCP_BUF_WRITE
2662 2662
 			if (unlikely(tcp_options.tcp_buf_write && 
2663 2663
 							_wbufq_non_empty(tcpconn) )){
2664
-				if (unlikely(TICKS_LE(t, tcpconn->wbuf_q.wr_timeout))){
2664
+				if (unlikely(TICKS_GE(t, tcpconn->wbuf_q.wr_timeout))){
2665 2665
 					DBG("handle_tcp_child: wr. timeout on CONN_RELEASE for %p "
2666 2666
 							"refcnt= %d\n", tcpconn,
2667 2667
 							atomic_get(&tcpconn->refcnt));
... ...
@@ -2772,6 +2772,9 @@ inline static int handle_ser_child(struct process_table* p, int fd_i)
2772 2772
 	int fd;
2773 2773
 	int flags;
2774 2774
 	ticks_t t;
2775
+#ifdef TCP_BUF_WRITE
2776
+	ticks_t nxt_timeout;
2777
+#endif /* TCP_BUF_WRITE */
2775 2778
 	
2776 2779
 	ret=-1;
2777 2780
 	if (unlikely(p->unix_sock<=0)){
... ...
@@ -2993,11 +2996,7 @@ inline static int handle_ser_child(struct process_table* p, int fd_i)
2993 2993
 			/* update the timeout*/
2994 2994
 			t=get_ticks_raw();
2995 2995
 			tcpconn->timeout=t+tcp_con_lifetime;
2996
-			/* activate the timer (already properly init. in tcpconn_new())
2997
-			 * no need for reinit */
2998
-			local_timer_add(&tcp_main_ltimer, &tcpconn->timer, 
2999
-								tcp_con_lifetime, t);
3000
-			tcpconn->flags|=F_CONN_MAIN_TIMER|F_CONN_READ_W|F_CONN_WANTS_RD;
2996
+			nxt_timeout=tcp_con_lifetime;
3001 2997
 			if (unlikely(cmd==CONN_NEW_COMPLETE)){
3002 2998
 				tcpconn->state=S_CONN_OK;
3003 2999
 				/* check if needs to be watched for write */
... ...
@@ -3005,8 +3004,18 @@ inline static int handle_ser_child(struct process_table* p, int fd_i)
3005 3005
 					/* if queue non empty watch it for write */
3006 3006
 					flags=(_wbufq_empty(tcpconn)-1)&POLLOUT;
3007 3007
 				lock_release(&tcpconn->write_lock);
3008
-				tcpconn->flags|=(!(flags&POLLOUT)-1)&
3009
-									(F_CONN_WRITE_W|F_CONN_WANTS_WR);
3008
+				if (flags){
3009
+					if (TICKS_LT(tcpconn->wbuf_q.wr_timeout, tcpconn->timeout)
3010
+							&& TICKS_LT(t, tcpconn->wbuf_q.wr_timeout))
3011
+						nxt_timeout=tcpconn->wbuf_q.wr_timeout-t;
3012
+					tcpconn->flags|=F_CONN_WRITE_W|F_CONN_WANTS_WR;
3013
+				}
3014
+				/* activate the timer (already properly init. in 
3015
+				   tcpconn_new())  no need for reinit */
3016
+				local_timer_add(&tcp_main_ltimer, &tcpconn->timer, nxt_timeout,
3017
+									t);
3018
+				tcpconn->flags|=F_CONN_MAIN_TIMER|F_CONN_READ_W| 
3019
+								F_CONN_WANTS_RD;
3010 3020
 			}else{
3011 3021
 				/* CONN_NEW_PENDING_WRITE */
3012 3022
 				/* we don't know if we successfully sent anything, but
... ...
@@ -3015,7 +3024,16 @@ inline static int handle_ser_child(struct process_table* p, int fd_i)
3015 3015
 				tcpconn->state=S_CONN_CONNECT;
3016 3016
 				/* no need to check, we have something queued for write */
3017 3017
 				flags=POLLOUT;
3018
-				tcpconn->flags|=(F_CONN_WRITE_W|F_CONN_WANTS_WR);
3018
+				if (TICKS_LT(tcpconn->wbuf_q.wr_timeout, tcpconn->timeout)
3019
+						&& TICKS_LT(t, tcpconn->wbuf_q.wr_timeout))
3020
+					nxt_timeout=tcpconn->wbuf_q.wr_timeout-t;
3021
+				/* activate the timer (already properly init. in 
3022
+				   tcpconn_new())  no need for reinit */
3023
+				local_timer_add(&tcp_main_ltimer, &tcpconn->timer, nxt_timeout,
3024
+									t);
3025
+				tcpconn->flags|=F_CONN_MAIN_TIMER|F_CONN_READ_W| 
3026
+								F_CONN_WANTS_RD |
3027
+								F_CONN_WRITE_W|F_CONN_WANTS_WR;
3019 3028
 			}
3020 3029
 			flags|=POLLIN;
3021 3030
 			if (unlikely(