Blame SOURCES/nfs-utils-1.3.0-mount-prognotreg.patch

e19a30
diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
e19a30
index bdd7c24..89b90a1 100644
e19a30
--- a/utils/mount/stropts.c
e19a30
+++ b/utils/mount/stropts.c
e19a30
@@ -931,19 +931,45 @@ static int nfs_try_mount(struct nfsmount_info *mi)
e19a30
  * failed so far, but fail immediately if there is a local
e19a30
  * error (like a bad mount option).
e19a30
  *
e19a30
- * ESTALE is also a temporary error because some servers
e19a30
- * return ESTALE when a share is temporarily offline.
e19a30
+ * If there is a remote error, like ESTALE or RPC_PROGNOTREGISTERED
e19a30
+ * then it is probably permanent, but there is a small chance
e19a30
+ * the it is temporary can we caught the server at an awkward
e19a30
+ * time during start-up.  So require that we see three of those
e19a30
+ * before treating them as permanent.
e19a30
+ * For ECONNREFUSED, wait a bit longer as there is often a longer
e19a30
+ * gap between the network being ready and the NFS server starting.
e19a30
  *
e19a30
  * Returns 1 if we should fail immediately, or 0 if we
e19a30
  * should retry.
e19a30
  */
e19a30
 static int nfs_is_permanent_error(int error)
e19a30
 {
e19a30
+	static int prev_error;
e19a30
+	static int rpt_cnt;
e19a30
+
e19a30
+	if (error == prev_error)
e19a30
+		rpt_cnt += 1;
e19a30
+	else
e19a30
+		rpt_cnt = 1;
e19a30
+	prev_error = error;
e19a30
+
e19a30
 	switch (error) {
e19a30
 	case ESTALE:
e19a30
-	case ETIMEDOUT:
e19a30
+	case EOPNOTSUPP:	/* aka RPC_PROGNOTREGISTERED */
e19a30
+		/* If two in a row, assume permanent */
e19a30
+		return rpt_cnt >= 3;
e19a30
 	case ECONNREFUSED:
e19a30
+		/* Like the above, this can be temporary during a
e19a30
+		 * small window.  However it is typically a larger
e19a30
+		 * window than for the others, and we have historically
e19a30
+		 * treated this as a temporary (i.e. long timeout)
e19a30
+		 * error with no complaints, so continue to treat
e19a30
+		 * it as temporary.
e19a30
+		 */
e19a30
+		return 0;	/* temporary */
e19a30
+	case ETIMEDOUT:
e19a30
 	case EHOSTUNREACH:
e19a30
+	case EAGAIN:
e19a30
 		return 0;	/* temporary */
e19a30
 	default:
e19a30
 		return 1;	/* permanent */
e19a30
@@ -987,7 +1013,7 @@ static int nfsmount_fg(struct nfsmount_info *mi)
e19a30
 			if (secs > 10)
e19a30
 				secs = 10;
e19a30
 		}
e19a30
-	};
e19a30
+	}
e19a30
 
e19a30
 	mount_error(mi->spec, mi->node, errno);
e19a30
 	return EX_FAIL;
e19a30
@@ -1005,8 +1031,7 @@ static int nfsmount_parent(struct nfsmount_info *mi)
e19a30
 	if (nfs_try_mount(mi))
e19a30
 		return EX_SUCCESS;
e19a30
 
e19a30
-	/* retry background mounts when the server is not up */
e19a30
-	if (nfs_is_permanent_error(errno) && errno != EOPNOTSUPP) {
e19a30
+	if (nfs_is_permanent_error(errno)) {
e19a30
 		mount_error(mi->spec, mi->node, errno);
e19a30
 		return EX_FAIL;
e19a30
 	}
e19a30
@@ -1041,8 +1066,7 @@ static int nfsmount_child(struct nfsmount_info *mi)
e19a30
 		if (nfs_try_mount(mi))
e19a30
 			return EX_SUCCESS;
e19a30
 
e19a30
-		/* retry background mounts when the server is not up */
e19a30
-		if (nfs_is_permanent_error(errno) && errno != EOPNOTSUPP)
e19a30
+		if (nfs_is_permanent_error(errno))
e19a30
 			break;
e19a30
 
e19a30
 		if (time(NULL) > timeout)