Blob Blame History Raw
autofs-5.0.6 - catch EHOSTUNREACH and bail out early

From: Ian Kent <raven@themaw.net>

Now that the lower layers of the rpc code has been reworked
to propogate error returns up to the top level code we can
catch the EHOSTUNREACH return and stop the probe since the
host isn't responding.

Also, since UDP is a broadcast protocol we don't get the
EHOSTUNREACH and always have to wait, so change the probe
order to try TCP first. Using UDP first was originally
done to reduce reserved port usage but autofs probing uses
higher numbered ports now so this shouldn't introduce
problem even for older implementations.
---

 CHANGELOG            |    1 
 include/replicated.h |    3 ++
 modules/replicated.c |   55 +++++++++++++++++++++++++++++++++++++--------------
 3 files changed, 44 insertions(+), 15 deletions(-)


--- autofs-5.0.6.orig/CHANGELOG
+++ autofs-5.0.6/CHANGELOG
@@ -28,6 +28,7 @@
 - add function to check mount.nfs version.
 - reinstate singleton mount probe.
 - rework error return handling in rpc code.
+- catch EHOSTUNREACH and bail out early.
 
 28/06/2011 autofs-5.0.6
 -----------------------
--- autofs-5.0.6.orig/include/replicated.h
+++ autofs-5.0.6/include/replicated.h
@@ -48,6 +48,9 @@
 #define TCP_SELECTED_MASK	0x00FF
 #define UDP_SELECTED_MASK	0xFF00
 
+#define IS_ERR(supported)	(0x8000 & supported)
+#define ERR(supported)		(IS_ERR(supported) ? (~supported + 1) : supported)
+
 #define RPC_TIMEOUT		5
 
 struct host {
--- autofs-5.0.6.orig/modules/replicated.c
+++ autofs-5.0.6/modules/replicated.c
@@ -563,7 +563,9 @@ static unsigned int get_nfs_info(unsigne
 		status = rpc_udp_getclient(rpc_info, NFS_PROGRAM, NFS4_VERSION);
 	else
 		status = rpc_tcp_getclient(rpc_info, NFS_PROGRAM, NFS4_VERSION);
-	if (!status) {
+	if (status == -EHOSTUNREACH)
+		return (unsigned int) status;
+	else if (!status) {
 		gettimeofday(&start, &tz);
 		status = rpc_ping_proto(rpc_info);
 		gettimeofday(&end, &tz);
@@ -589,7 +591,10 @@ v3_ver:
 		status = rpc_portmap_getclient(pm_info,
 				host->name, host->addr, host->addr_len,
 				proto, RPC_CLOSE_DEFAULT);
-		if (status)
+		if (status == -EHOSTUNREACH) {
+			supported = status;
+			goto done_ver;
+		} else if (status)
 			goto done_ver;
 	}
 
@@ -602,16 +607,23 @@ v3_ver:
 	} else {
 		parms.pm_prot = rpc_info->proto->p_proto;
 		parms.pm_vers = NFS3_VERSION;
-		rpc_info->port = rpc_portmap_getport(pm_info, &parms);
-		if (rpc_info->port < 0)
+		status = rpc_portmap_getport(pm_info, &parms);
+		if (status == -EHOSTUNREACH) {
+			supported = status;
+			goto done_ver;
+		} else if (status < 0)
 			goto v2_ver;
+		rpc_info->port = status;
 	}
 
 	if (rpc_info->proto->p_proto == IPPROTO_UDP)
 		status = rpc_udp_getclient(rpc_info, NFS_PROGRAM, NFS3_VERSION);
 	else
 		status = rpc_tcp_getclient(rpc_info, NFS_PROGRAM, NFS3_VERSION);
-	if (!status) {
+	if (status == -EHOSTUNREACH) {
+		supported = status;
+		goto done_ver;
+	} else if (!status) {
 		gettimeofday(&start, &tz);
 		status = rpc_ping_proto(rpc_info);
 		gettimeofday(&end, &tz);
@@ -643,15 +655,23 @@ v2_ver:
 		parms.pm_prot = rpc_info->proto->p_proto;
 		parms.pm_vers = NFS2_VERSION;
 		rpc_info->port = rpc_portmap_getport(pm_info, &parms);
-		if (rpc_info->port < 0)
+		status = rpc_portmap_getport(pm_info, &parms);
+		if (status == -EHOSTUNREACH) {
+			supported = status;
+			goto done_ver;
+		} else if (status < 0)
 			goto done_ver;
+		rpc_info->port = status;
 	}
 
 	if (rpc_info->proto->p_proto == IPPROTO_UDP)
 		status = rpc_udp_getclient(rpc_info, NFS_PROGRAM, NFS2_VERSION);
 	else
 		status = rpc_tcp_getclient(rpc_info, NFS_PROGRAM, NFS2_VERSION);
-	if (!status) {
+	if (status == -EHOSTUNREACH) {
+		supported = status;
+		goto done_ver;
+	} else if (!status) {
 		gettimeofday(&start, &tz);
 		status = rpc_ping_proto(rpc_info);
 		gettimeofday(&end, &tz);
@@ -728,21 +748,24 @@ static int get_vers_and_cost(unsigned lo
 
 	vers &= version;
 
-	if (version & UDP_REQUESTED) {
+	if (version & TCP_REQUESTED) {
 		supported = get_nfs_info(logopt, host,
-				   &pm_info, &rpc_info, "udp", vers, options);
-		if (supported) {
+				   &pm_info, &rpc_info, "tcp", vers, options);
+		if (IS_ERR(supported)) {
+			if (ERR(supported) == EHOSTUNREACH)
+				return ret;
+		} else if (supported) {
 			ret = 1;
-			host->version |= (supported << 8);
+			host->version |= supported;
 		}
 	}
 
-	if (version & TCP_REQUESTED) {
+	if (version & UDP_REQUESTED) {
 		supported = get_nfs_info(logopt, host,
-				   &pm_info, &rpc_info, "tcp", vers, options);
+				   &pm_info, &rpc_info, "udp", vers, options);
 		if (supported) {
 			ret = 1;
-			host->version |= supported;
+			host->version |= (supported << 8);
 		}
 	}
 
@@ -848,7 +871,9 @@ static int get_supported_ver_and_cost(un
 		status = rpc_udp_getclient(&rpc_info, NFS_PROGRAM, parms.pm_vers);
 	else
 		status = rpc_tcp_getclient(&rpc_info, NFS_PROGRAM, parms.pm_vers);
-	if (!status) {
+	if (status == -EHOSTUNREACH)
+		goto done;
+	else if (!status) {
 		gettimeofday(&start, &tz);
 		status = rpc_ping_proto(&rpc_info);
 		gettimeofday(&end, &tz);