Date: Mon, 14 Jan 2013 14:37:04 -0500 From: John Baldwin <jhb@freebsd.org> To: fs@freebsd.org Cc: Rick Macklem <rmacklem@freebsd.org>, Doug Rabson <dfr@freebsd.org> Subject: [PATCH] Properly handle signals on interruptible NFS mounts Message-ID: <201301141437.05040.jhb@freebsd.org>
next in thread | raw e-mail | index | archive | help
When the new RPC layer was brought in, the RPC_INTR return value (to indicate an RPC request was interrupted by a signal) was not handled in the NFS client. As a result, if an NFS request is interrupted by a signal (on a mount with the "intr" option), then the nfs_request() functions would fall through to the default case and return EACCES rather than EINTR. While here, I noticed that the new RPC layer also lost all of the RPC statistics the old client used to keep (but that are still reported in 'nfsstat -c'). I've added back as many of the statistics as I could, but retries are not easy to do as only the RPC layer knows about them and not the NFS client. Index: fs/nfs/nfs_commonkrpc.c =================================================================== --- fs/nfs/nfs_commonkrpc.c (revision 245225) +++ fs/nfs/nfs_commonkrpc.c (working copy) @@ -767,12 +767,18 @@ if (stat == RPC_SUCCESS) { error = 0; } else if (stat == RPC_TIMEDOUT) { + NFSINCRGLOBAL(newnfsstats.rpctimeouts); error = ETIMEDOUT; } else if (stat == RPC_VERSMISMATCH) { + NFSINCRGLOBAL(newnfsstats.rpcinvalid); error = EOPNOTSUPP; } else if (stat == RPC_PROGVERSMISMATCH) { + NFSINCRGLOBAL(newnfsstats.rpcinvalid); error = EPROTONOSUPPORT; + } else if (stat == RPC_INTR) { + error = EINTR; } else { + NFSINCRGLOBAL(newnfsstats.rpcinvalid); error = EACCES; } if (error) { Index: nfsclient/nfs_krpc.c =================================================================== --- nfsclient/nfs_krpc.c (revision 245225) +++ nfsclient/nfs_krpc.c (working copy) @@ -549,14 +549,21 @@ */ if (stat == RPC_SUCCESS) error = 0; - else if (stat == RPC_TIMEDOUT) + else if (stat == RPC_TIMEDOUT) { + nfsstats.rpctimeouts++; error = ETIMEDOUT; - else if (stat == RPC_VERSMISMATCH) + } else if (stat == RPC_VERSMISMATCH) { + nfsstats.rpcinvalid++; error = EOPNOTSUPP; - else if (stat == RPC_PROGVERSMISMATCH) + } else if (stat == RPC_PROGVERSMISMATCH) { + nfsstats.rpcinvalid++; error = EPROTONOSUPPORT; - else + } else if (stat == RPC_INTR) { + error = EINTR; + } else { + nfsstats.rpcinvalid++; error = EACCES; + } if (error) goto nfsmout; @@ -572,6 +579,7 @@ if (error == ENOMEM) { m_freem(mrep); AUTH_DESTROY(auth); + nfsstats.rpcinvalid++; return (error); } -- John Baldwin
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201301141437.05040.jhb>