|
|
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)
|