Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 10 Jun 2018 22:11:51 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r334934 - in projects/pnfs-planb-server/sys/fs: nfs nfsclient
Message-ID:  <201806102211.w5AMBp9o091914@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rmacklem
Date: Sun Jun 10 22:11:51 2018
New Revision: 334934
URL: https://svnweb.freebsd.org/changeset/base/334934

Log:
  Add code that sets the session defunct after a "soft" mount has returned
  an error without completing the RPC.
  Without this, if a DS server is down for a long time, RPCs will use up
  all the session slots and then processes will hang waiting for a slot.
  Once an RPC has returned error without completion, the state of the session
  slot is unknown, so setting it defunct seems to be the only option.
  Also, add EIO to ENXIO for the case where a DS replies NFSERR_IO to report
  I/O problems on the server.

Modified:
  projects/pnfs-planb-server/sys/fs/nfs/nfs_commonkrpc.c
  projects/pnfs-planb-server/sys/fs/nfsclient/nfs_clrpcops.c

Modified: projects/pnfs-planb-server/sys/fs/nfs/nfs_commonkrpc.c
==============================================================================
--- projects/pnfs-planb-server/sys/fs/nfs/nfs_commonkrpc.c	Sun Jun 10 21:36:29 2018	(r334933)
+++ projects/pnfs-planb-server/sys/fs/nfs/nfs_commonkrpc.c	Sun Jun 10 22:11:51 2018	(r334934)
@@ -810,6 +810,56 @@ tryagain:
 		error = EINTR;
 	} else if (stat == RPC_CANTSEND || stat == RPC_CANTRECV ||
 	     stat == RPC_SYSTEMERROR) {
+		if ((nd->nd_flag & ND_NFSV41) != 0 && nmp != NULL &&
+		    nd->nd_procnum != NFSPROC_NULL) {
+			/*
+			 * The nfsess_defunct field is protected by
+			 * the NFSLOCKMNT()/nm_mtx lock and not the
+			 * nfsess_mtx lock to simplify its handling,
+			 * for the MDS session. This lock is also
+			 * sufficient for nfsess_sessionid, since it
+			 * never changes in the structure.
+			 */
+			NFSLOCKCLSTATE();
+			NFSLOCKMNT(nmp);
+			/* The session must be marked defunct. */
+			if (dssep == NULL) {
+				/*
+				 * This is either an MDS proxy operation or
+				 * a client mount with "soft,retrans=N" options.
+				 * Mark the MDS session defunct and initiate
+				 * recovery, as required.
+				 */
+				NFSCL_DEBUG(1, "Failed soft proxy RPC\n");
+				sep = NFSMNT_MDSSESSION(nmp);
+				if (bcmp(sep->nfsess_sessionid, nd->nd_sequence,
+				    NFSX_V4SESSIONID) == 0) {
+					/* Initiate recovery. */
+					sep->nfsess_defunct = 1;
+					NFSCL_DEBUG(1, "Marked defunct\n");
+					if (nmp->nm_clp != NULL) {
+						nmp->nm_clp->nfsc_flags |=
+						    NFSCLFLAGS_RECOVER;
+						wakeup(nmp->nm_clp);
+					}
+				}
+			} else {
+				/*
+				 * This is a client side DS RPC. Just mark
+				 * the session defunct.  A subsequent LayoutGet
+				 * should get a new session.
+				 */
+				NFSCL_DEBUG(1, "Failed client DS RPC\n");
+				if (bcmp(dssep->nfsess_sessionid,
+				    nd->nd_sequence, NFSX_V4SESSIONID) == 0) {
+					/* Mark it defunct. */
+					dssep->nfsess_defunct = 1;
+					NFSCL_DEBUG(1, "Marked defunct\n");
+				}
+			}
+			NFSUNLOCKMNT(nmp);
+			NFSUNLOCKCLSTATE();
+		}
 		NFSINCRGLOBAL(nfsstatsv1.rpcinvalid);
 		error = ENXIO;
 	} else {

Modified: projects/pnfs-planb-server/sys/fs/nfsclient/nfs_clrpcops.c
==============================================================================
--- projects/pnfs-planb-server/sys/fs/nfsclient/nfs_clrpcops.c	Sun Jun 10 21:36:29 2018	(r334933)
+++ projects/pnfs-planb-server/sys/fs/nfsclient/nfs_clrpcops.c	Sun Jun 10 22:11:51 2018	(r334934)
@@ -6040,8 +6040,14 @@ nfscl_dofflayoutio(vnode_t vp, struct uio *uiop, int *
 					    *dspp, fhp, dp->nfsdi_vers,
 					    dp->nfsdi_minorvers, tcred, p);
 				NFSCL_DEBUG(4, "commitds=%d\n", error);
-				/* ENXIO indicates a problem with the DS. */
-				if (error == ENXIO) {
+				/*
+				 * ENXIO indicates that the krpc cannot do
+				 * an RPC on the DS.  EIO is returned by the
+				 * RPC as an indication of I/O problems on the
+				 * server.
+				 * Are there other fatal errors?
+				 */
+				if (error == ENXIO || error == EIO) {
 					NFSCL_DEBUG(4,
 					    "DS layreterr for commit\n");
 					nfscl_dserr(NFSV4OP_COMMIT, dp, lyp);
@@ -6065,8 +6071,14 @@ nfscl_dofflayoutio(vnode_t vp, struct uio *uiop, int *
 			    off, xfer, fhp, 1, dp->nfsdi_vers,
 			    dp->nfsdi_minorvers, tcred, p);
 			NFSCL_DEBUG(4, "readds=%d\n", error);
-			if (error == ENXIO) {
-				/* ENXIO indicates a problem with the DS. */
+			if (error == ENXIO || error == EIO) {
+				/*
+				 * ENXIO indicates that the krpc cannot do
+				 * an RPC on the DS.  EIO is returned by the
+				 * RPC as an indication of I/O problems on the
+				 * server.
+				 * Are there other fatal errors?
+				 */
 				NFSCL_DEBUG(4, "DS layreterr for read\n");
 				nfscl_dserr(NFSV4OP_READ, dp, lyp);
 			}
@@ -6101,8 +6113,14 @@ nfscl_dofflayoutio(vnode_t vp, struct uio *uiop, int *
 					    xfer, fhp, m, dp->nfsdi_vers,
 					    dp->nfsdi_minorvers, tcred, p);
 				NFSCL_DEBUG(4, "nfsio_writedsmir=%d\n", error);
-				if (error == ENXIO) {
-					/* ENXIO indicates a DS problem. */
+				if (error == ENXIO || error == EIO) {
+					/*
+					 * ENXIO indicates that the krpc cannot
+					 * do an RPC on the DS.  EIO is returned
+					 * by the RPC as an indication of I/O
+					 * problems on the server.
+					 * Are there other fatal errors?
+					 */
 					NFSCL_DEBUG(4,
 					    "DS layreterr for write\n");
 					nfscl_dserr(NFSV4OP_WRITE, dp, lyp);



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