Skip to contentSkip to conversation

retry for NFS v3 mounts

PATCH In review Dick Streefland 2 participants 4 messages Dec 1, 2011 – Dec 5, 2011

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 retry for NFS v3 mounts

Mounting an NFS v3 volume from a server that is currently down, immediately fails with a timeout error, instead of retrying:

# mount -t nfs -v -overs=3,proto=udp,bg server:/foo /mnt
mount.nfs: trying text-based options 'vers=3,proto=udp,bg,addr=172.17.2.94'
mount.nfs: prog 100003, trying vers=3, prot=17
mount.nfs: portmap query failed: RPC: Timed out

mount.nfs: mount to NFS server 'server:/foo' failed: timed out, giving up

# mount -t nfs -v -overs=3,proto=tcp,bg server:/foo /mnt
mount.nfs: trying text-based options 'vers=3,proto=tcp,bg,addr=172.17.2.94'
mount.nfs: prog 100003, trying vers=3, prot=6
mount.nfs: portmap query failed: RPC: Remote system error - No route to host

mount.nfs: No route to host

As a result, NFS mounts may not come up after a power failure when the client boots faster than the server. The attached patch for nfs-utils adds ESPIPE to the list of errors considered temporary, so that the mount will be retried:

# mount -t nfs -v -overs=3,proto=udp,bg server:/foo /mnt
mount.nfs: trying text-based options 'vers=3,proto=udp,bg,addr=172.17.2.94'
mount.nfs: prog 100003, trying vers=3, prot=17
mount.nfs: portmap query failed: RPC: Timed out

mount.nfs: backgrounding "server:/foo"
mount.nfs: mount options: "vers=3,proto=udp,bg,addr=172.17.2.94"

# mount -t nfs -v -overs=3,proto=tcp,bg server:/foo /mnt
mount.nfs: trying text-based options 'vers=3,proto=tcp,bg,addr=172.17.2.94'
mount.nfs: prog 100003, trying vers=3, prot=6
mount.nfs: portmap query failed: RPC: Remote system error - No route to host

mount.nfs: backgrounding "server:/foo"
mount.nfs: mount options: "vers=3,proto=tcp,bg,addr=172.17.2.94"

utils/mount/stropts.c +2 -0
index 4032bf3..7ca0b3e 100644
@@ -663,6 +663,7 @@ static int nfs_try_mount_v3v2(struct nfsmount_info *mi)
 		case ECONNREFUSED:
 		case EOPNOTSUPP:
 		case EHOSTUNREACH:
+		case ESPIPE:
 			continue;
 		default:
 			goto out;
@@ -848,6 +849,7 @@ static int nfs_is_permanent_error(int error)
 	case ETIMEDOUT:
 	case ECONNREFUSED:
 	case EHOSTUNREACH:
+	case ESPIPE:
 		return 0;	/* temporary */
 	default:
 		return 1;	/* permanent */
Signature · 1 line
Dick
#1 lore raw

Hello,

Quoted 17 lines · On 12/01/2011 12:33 PM, [email protected] wrote:

Mounting an NFS v3 volume from a server that is currently down, immediately fails with a timeout error, instead of retrying:

utils/mount/stropts.c +1 -0
index 4032bf3..7ca0b3e 100644
@@ -663,6 +663,7 @@ static int nfs_try_mount_v3v2(struct nfsmount_info *mi)
 		case ECONNREFUSED:
 		case EOPNOTSUPP:
 		case EHOSTUNREACH:
+		case ESPIPE:
 			continue;
 		default:
 			goto out;

utils/mount/stropts.c static int nfs_is_permanent_error(int error) · line 855

Quoted 7 lines
utils/mount/stropts.c +1 -0
@@ -848,6 +849,7 @@ static int nfs_is_permanent_error(int error)
 	case ETIMEDOUT:
 	case ECONNREFUSED:
 	case EHOSTUNREACH:
+	case ESPIPE:
 		return 0;	/* temporary */
 	default:
 		return 1;	/* permanent */

I think the problem is more of nfs_rewrite_pmap_mount_options() is not interrupting RPC correctly.... How about something like this:

Author: Steve Dickson <[email protected]>
Date:   Thu Dec 1 15:35:18 2011 -0500

mount.nfs: Background mounts failing on time out errors.

Mounting with the "-o v3,bg,proto=udp" options will fail, instead of trying, when the server is down. The reason being nfs_rewrite_pmap_mount_options() is not interrupting RPC timeouts correctly.

utils/mount/stropts.c +2 -0
index 4032bf3..d52e21a 100644
@@ -540,6 +540,8 @@ nfs_rewrite_pmap_mount_options(struct mount_options *options
                        errno = EOPNOTSUPP;
                else if (rpc_createerr.cf_stat == RPC_AUTHERROR)
                        errno = EACCES;
+               else if (rpc_createerr.cf_stat == RPC_TIMEDOUT)
+                       errno = ETIMEDOUT;
                else if (rpc_createerr.cf_error.re_errno != 0)
                        errno = rpc_createerr.cf_error.re_errno;
                return 0;
#2 lore raw

Steve Dickson <[email protected]> wrote:
| I think the problem is more of nfs_rewrite_pmap_mount_options() | is not interrupting RPC correctly.... How about something like this:
[...]
| + else if (rpc_createerr.cf_stat == RPC_TIMEDOUT)
| + errno = ETIMEDOUT;

OK, that works as well.

Signature · 1 line
Dick
#3 lore raw
In reply to Steve Dickson
Quoted 47 lines · Steve Dickson

Hello,

Quoted 16 lines · On 12/01/2011 12:33 PM, [email protected] wrote:
Quoted 16 lines

Mounting an NFS v3 volume from a server that is currently down, immediately fails with a timeout error, instead of retrying:

utils/mount/stropts.c +1 -0
index 4032bf3..7ca0b3e 100644
@@ -663,6 +663,7 @@ static int nfs_try_mount_v3v2(struct nfsmount_info *mi)
 		case ECONNREFUSED:
 		case EOPNOTSUPP:
 		case EHOSTUNREACH:
+		case ESPIPE:
 			continue;
 		default:
 			goto out;
@@ -848,6 +849,7 @@ static int nfs_is_permanent_error(int error)
Quoted 8 lines

utils/mount/stropts.c static int nfs_is_permanent_error(int error) · line 855

Quoted 8 lines
utils/mount/stropts.c +1 -0
 	case ETIMEDOUT:
 	case ECONNREFUSED:
 	case EHOSTUNREACH:
+	case ESPIPE:
 		return 0;	/* temporary */
 	default:
 		return 1;	/* permanent */

I think the problem is more of nfs_rewrite_pmap_mount_options() is not interrupting RPC correctly.... How about something like this:

Author: Steve Dickson <[email protected]>
Date:   Thu Dec 1 15:35:18 2011 -0500

mount.nfs: Background mounts failing on time out errors.

Mounting with the "-o v3,bg,proto=udp" options will fail, instead of trying, when the server is down. The reason being nfs_rewrite_pmap_mount_options() is not interrupting RPC timeouts correctly.

utils/mount/stropts.c +0 -0
index 4032bf3..d52e21a 100644

utils/mount/stropts.c nfs_rewrite_pmap_mount_options(struct mount_options *options · line 547

Quoted 8 lines
utils/mount/stropts.c +2 -0
@@ -540,6 +540,8 @@ nfs_rewrite_pmap_mount_options(struct mount_options *options
                        errno = EOPNOTSUPP;
                else if (rpc_createerr.cf_stat == RPC_AUTHERROR)
                        errno = EACCES;
+               else if (rpc_createerr.cf_stat == RPC_TIMEDOUT)
+                       errno = ETIMEDOUT;
                else if (rpc_createerr.cf_error.re_errno != 0)
                        errno = rpc_createerr.cf_error.re_errno;
                return 0;

Committed...

steved.