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
This commit is contained in:
parent
d793587fe2
commit
502b7cf99b
@ -416,8 +416,13 @@ readip(struct iodesc *d, void **pkt, void **payload, time_t tleft,
|
|||||||
while ((getsecs() - t) < tleft) {
|
while ((getsecs() - t) < tleft) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
ret = readipv4(d, pkt, payload, tleft, proto);
|
ret = readipv4(d, pkt, payload, tleft, proto);
|
||||||
|
if (ret >= 0)
|
||||||
|
return (ret);
|
||||||
|
/* Bubble up the error if it wasn't successful */
|
||||||
if (errno != EAGAIN)
|
if (errno != EAGAIN)
|
||||||
break;
|
return (-1);
|
||||||
}
|
}
|
||||||
return (ret);
|
/* We've exhausted tleft; timeout */
|
||||||
|
errno = ETIMEDOUT;
|
||||||
|
return (-1);
|
||||||
}
|
}
|
||||||
|
@ -118,7 +118,7 @@ sendrecv(struct iodesc *d,
|
|||||||
/* Try to get a packet and process it. */
|
/* Try to get a packet and process it. */
|
||||||
cc = (*rproc)(d, pkt, payload, tleft);
|
cc = (*rproc)(d, pkt, payload, tleft);
|
||||||
/* Return on data, EOF or real error. */
|
/* Return on data, EOF or real error. */
|
||||||
if (cc != -1 || errno != 0)
|
if (cc != -1 || (errno != 0 && errno != ETIMEDOUT))
|
||||||
return (cc);
|
return (cc);
|
||||||
|
|
||||||
/* Timed out or didn't get the packet we're waiting for */
|
/* Timed out or didn't get the packet we're waiting for */
|
||||||
|
@ -638,14 +638,20 @@ sendrecv_tftp(struct tftp_handle *h,
|
|||||||
if (cc == -1) {
|
if (cc == -1) {
|
||||||
/* Error on transmit; wait before retrying */
|
/* Error on transmit; wait before retrying */
|
||||||
while ((getsecs() - t1) < tleft);
|
while ((getsecs() - t1) < tleft);
|
||||||
|
t1 = getsecs();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t = t1 = getsecs();
|
||||||
recvnext:
|
recvnext:
|
||||||
|
if ((getsecs() - t) > MAXTMO) {
|
||||||
|
errno = ETIMEDOUT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
/* Try to get a packet and process it. */
|
/* Try to get a packet and process it. */
|
||||||
cc = (*rproc)(h, pkt, payload, tleft, rtype);
|
cc = (*rproc)(h, pkt, payload, tleft, rtype);
|
||||||
/* Return on data, EOF or real error. */
|
/* Return on data, EOF or real error. */
|
||||||
if (cc != -1 || errno != 0)
|
if (cc != -1 || (errno != 0 && errno != ETIMEDOUT))
|
||||||
return (cc);
|
return (cc);
|
||||||
if ((getsecs() - t1) < tleft) {
|
if ((getsecs() - t1) < tleft) {
|
||||||
goto recvnext;
|
goto recvnext;
|
||||||
|
Loading…
Reference in New Issue
Block a user