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