Author: kevans
Date: Wed Feb 14 15:40:13 2018
New Revision: 329264
URL: https://svnweb.freebsd.org/changeset/base/329264

Log:
  libsa: Fix IP recv timeout
  
  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.
  
  Reported by:  sbruno
  Reviewed by:  sbruno, tsoome
  MFC after:    3 days
  Differential Revision:        https://reviews.freebsd.org/D14350

Modified:
  head/stand/libsa/ip.c
  head/stand/libsa/net.c
  head/stand/libsa/tftp.c

Modified: head/stand/libsa/ip.c
==============================================================================
--- head/stand/libsa/ip.c       Wed Feb 14 15:14:20 2018        (r329263)
+++ head/stand/libsa/ip.c       Wed Feb 14 15:40:13 2018        (r329264)
@@ -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: head/stand/libsa/net.c
==============================================================================
--- head/stand/libsa/net.c      Wed Feb 14 15:14:20 2018        (r329263)
+++ head/stand/libsa/net.c      Wed Feb 14 15:40:13 2018        (r329264)
@@ -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: head/stand/libsa/tftp.c
==============================================================================
--- head/stand/libsa/tftp.c     Wed Feb 14 15:14:20 2018        (r329263)
+++ head/stand/libsa/tftp.c     Wed Feb 14 15:40:13 2018        (r329264)
@@ -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;
                }
 
+               t = 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;
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to