summaryrefslogtreecommitdiff
path: root/sys/nfs
diff options
context:
space:
mode:
authormarius eriksen <marius@cvs.openbsd.org>2004-07-10 20:39:16 +0000
committermarius eriksen <marius@cvs.openbsd.org>2004-07-10 20:39:16 +0000
commit3f2f30fb501541c85ed825e301e3363544f81ac5 (patch)
treef1de627ea9943cee368ad4b2a60f52bc3207235b /sys/nfs
parentb18fea504f7375e2e3b77fd2bc2a12f688560258 (diff)
fix for where a TCP NFS connection could sleep in soreceive() forever,
this fixes some problems people have experienced with NFS mounts freezing on NFS server reboot/crash. ok deraadt@ pedro@ tholo@
Diffstat (limited to 'sys/nfs')
-rw-r--r--sys/nfs/nfs_socket.c26
1 files changed, 22 insertions, 4 deletions
diff --git a/sys/nfs/nfs_socket.c b/sys/nfs/nfs_socket.c
index c6d124ea87f..5ec4ee08117 100644
--- a/sys/nfs/nfs_socket.c
+++ b/sys/nfs/nfs_socket.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: nfs_socket.c,v 1.37 2004/06/24 19:35:26 tholo Exp $ */
+/* $OpenBSD: nfs_socket.c,v 1.38 2004/07/10 20:39:15 marius Exp $ */
/* $NetBSD: nfs_socket.c,v 1.27 1996/04/15 20:20:00 thorpej Exp $ */
/*
@@ -242,7 +242,12 @@ nfs_connect(nmp, rep)
so->so_rcv.sb_timeo = (5 * hz);
so->so_snd.sb_timeo = (5 * hz);
} else {
- so->so_rcv.sb_timeo = 0;
+ /*
+ * enable receive timeout to detect server crash and
+ * reconnect. otherwise, we can be stuck in soreceive
+ * forever.
+ */
+ so->so_rcv.sb_timeo = (5 * hz);
so->so_snd.sb_timeo = 0;
}
if (nmp->nm_sotype == SOCK_DGRAM) {
@@ -322,10 +327,11 @@ nfs_reconnect(rep)
* Loop through outstanding request list and fix up all requests
* on old socket.
*/
- for (rp = TAILQ_FIRST(&nfs_reqq); rp != NULL;
- rp = TAILQ_NEXT(rp, r_chain)) {
+ TAILQ_FOREACH(rp, &nfs_reqq, r_chain) {
if (rp->r_nmp == nmp)
rp->r_flags |= R_MUSTRESEND;
+
+ rp->r_rexmit = 0;
}
return (0);
}
@@ -490,6 +496,8 @@ tryagain:
while (rep->r_flags & R_MUSTRESEND) {
m = m_copym(rep->r_mreq, 0, M_COPYALL, M_WAIT);
nfsstats.rpcretries++;
+ rep->r_rtt = 0;
+ rep->r_flags &= ~R_TIMING;
error = nfs_send(so, rep->r_nmp->nm_nam, m, rep);
if (error) {
if (error == EINTR || error == ERESTART ||
@@ -518,6 +526,16 @@ tryagain:
if (error == EWOULDBLOCK && rep) {
if (rep->r_flags & R_SOFTTERM)
return (EINTR);
+ /*
+ * looks like the server died after it
+ * received the request, make sure
+ * that we will retransmit and we
+ * don't get stuck here forever.
+ */
+ if (rep->r_rexmit >= rep->r_nmp->nm_retry) {
+ nfsstats.rpctimeouts++;
+ error = EPIPE;
+ }
}
} while (error == EWOULDBLOCK);
if (!error && auio.uio_resid > 0) {