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

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