Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 17 Feb 2018 02:14:01 +0000 (UTC)
From:      Kyle Evans <kevans@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r329423 - stable/11/stand/libsa
Message-ID:  <201802170214.w1H2E1Vg085541@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kevans
Date: Sat Feb 17 02:14:01 2018
New Revision: 329423
URL: https://svnweb.freebsd.org/changeset/base/329423

Log:
  MFC r329264: libsa: Fix IP recv timeout
  
  [This is slightly modified to not set `t` in the middle of the loop so that
  the connection will eventually timeout after MAXTMO]
  
  readip() doesn't, at the moment, properly indicate to callers that it has
  timed out. One can tell that it's timed out if errno == EAGAIN when it
  returns, but this is not ideal. Restructure it a little bit to explicitly
  set errno to ETIMEDOUT if we've exhausted tleft.
  
  I found two places that care about where it timed out or not: sendrecv in
  net.c and sendrecv_tftp. Both are structured to pass smaller timeout values
  to readip while tracking a larger timeout. Neither of them were able to do
  this properly with readip not indicating ETIMEDOUT, so fix it.
  
  While here, straighten out the time (t/t1) usage in sendrecv_tftp.
  
  This would have manifested itself in periodic failures to NFS/TFTP boot for
  no apparent reason because MINTMO/MAXTMO were not actually being respected
  properly. Problems were not reported with NFS, only TFTP.

Modified:
  stable/11/stand/libsa/ip.c
  stable/11/stand/libsa/net.c
  stable/11/stand/libsa/tftp.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/stand/libsa/ip.c
==============================================================================
--- stable/11/stand/libsa/ip.c	Sat Feb 17 00:24:50 2018	(r329422)
+++ stable/11/stand/libsa/ip.c	Sat Feb 17 02:14:01 2018	(r329423)
@@ -416,8 +416,13 @@ readip(struct iodesc *d, void **pkt, void **payload, t
 	while ((getsecs() - t) < tleft) {
 		errno = 0;
 		ret = readipv4(d, pkt, payload, tleft, proto);
+		if (ret >= 0)
+			return (ret);
+		/* Bubble up the error if it wasn't successful */
 		if (errno != EAGAIN)
-			break;
+			return (-1);
 	}
-	return (ret);
+	/* We've exhausted tleft; timeout */
+	errno = ETIMEDOUT;
+	return (-1);
 }

Modified: stable/11/stand/libsa/net.c
==============================================================================
--- stable/11/stand/libsa/net.c	Sat Feb 17 00:24:50 2018	(r329422)
+++ stable/11/stand/libsa/net.c	Sat Feb 17 02:14:01 2018	(r329423)
@@ -118,7 +118,7 @@ sendrecv(struct iodesc *d,
 		/* Try to get a packet and process it. */
 		cc = (*rproc)(d, pkt, payload, tleft);
 		/* Return on data, EOF or real error. */
-		if (cc != -1 || errno != 0)
+		if (cc != -1 || (errno != 0 && errno != ETIMEDOUT))
 			return (cc);
 
 		/* Timed out or didn't get the packet we're waiting for */

Modified: stable/11/stand/libsa/tftp.c
==============================================================================
--- stable/11/stand/libsa/tftp.c	Sat Feb 17 00:24:50 2018	(r329422)
+++ stable/11/stand/libsa/tftp.c	Sat Feb 17 02:14:01 2018	(r329423)
@@ -638,14 +638,20 @@ sendrecv_tftp(struct tftp_handle *h,
 		if (cc == -1) {
 			/* Error on transmit; wait before retrying */
 			while ((getsecs() - t1) < tleft);
+			t1 = getsecs();
 			continue;
 		}
 
+		t1 = getsecs();
 recvnext:
+		if ((getsecs() - t) > MAXTMO) {
+			errno = ETIMEDOUT;
+			return -1;
+		}
 		/* Try to get a packet and process it. */
 		cc = (*rproc)(h, pkt, payload, tleft, rtype);
 		/* Return on data, EOF or real error. */
-		if (cc != -1 || errno != 0)
+		if (cc != -1 || (errno != 0 && errno != ETIMEDOUT))
 			return (cc);
 		if ((getsecs() - t1) < tleft) {
 		    goto recvnext;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201802170214.w1H2E1Vg085541>