Ian Kent 5ec16e
autofs-5.0.6 - catch EHOSTUNREACH and bail out early
Ian Kent 5ec16e
Ian Kent 5ec16e
From: Ian Kent <raven@themaw.net>
Ian Kent 5ec16e
Ian Kent 5ec16e
Now that the lower layers of the rpc code has been reworked
Ian Kent 5ec16e
to propogate error returns up to the top level code we can
Ian Kent 5ec16e
catch the EHOSTUNREACH return and stop the probe since the
Ian Kent 5ec16e
host isn't responding.
Ian Kent 5ec16e
Ian Kent 5ec16e
Also, since UDP is a broadcast protocol we don't get the
Ian Kent 5ec16e
EHOSTUNREACH and always have to wait, so change the probe
Ian Kent 5ec16e
order to try TCP first. Using UDP first was originally
Ian Kent 5ec16e
done to reduce reserved port usage but autofs probing uses
Ian Kent 5ec16e
higher numbered ports now so this shouldn't introduce
Ian Kent 5ec16e
problem even for older implementations.
Ian Kent 5ec16e
---
Ian Kent 5ec16e
Ian Kent 5ec16e
 CHANGELOG            |    1 
Ian Kent 5ec16e
 include/replicated.h |    3 ++
Ian Kent 5ec16e
 modules/replicated.c |   55 +++++++++++++++++++++++++++++++++++++--------------
Ian Kent 5ec16e
 3 files changed, 44 insertions(+), 15 deletions(-)
Ian Kent 5ec16e
Ian Kent 5ec16e
Ian Kent 5ec16e
--- autofs-5.0.6.orig/CHANGELOG
Ian Kent 5ec16e
+++ autofs-5.0.6/CHANGELOG
Ian Kent 5ec16e
@@ -28,6 +28,7 @@
Ian Kent 5ec16e
 - add function to check mount.nfs version.
Ian Kent 5ec16e
 - reinstate singleton mount probe.
Ian Kent 5ec16e
 - rework error return handling in rpc code.
Ian Kent 5ec16e
+- catch EHOSTUNREACH and bail out early.
Ian Kent 5ec16e
 
Ian Kent 5ec16e
 28/06/2011 autofs-5.0.6
Ian Kent 5ec16e
 -----------------------
Ian Kent 5ec16e
--- autofs-5.0.6.orig/include/replicated.h
Ian Kent 5ec16e
+++ autofs-5.0.6/include/replicated.h
Ian Kent 5ec16e
@@ -48,6 +48,9 @@
Ian Kent 5ec16e
 #define TCP_SELECTED_MASK	0x00FF
Ian Kent 5ec16e
 #define UDP_SELECTED_MASK	0xFF00
Ian Kent 5ec16e
 
Ian Kent 5ec16e
+#define IS_ERR(supported)	(0x8000 & supported)
Ian Kent 5ec16e
+#define ERR(supported)		(IS_ERR(supported) ? (~supported + 1) : supported)
Ian Kent 5ec16e
+
Ian Kent 5ec16e
 #define RPC_TIMEOUT		5
Ian Kent 5ec16e
 
Ian Kent 5ec16e
 struct host {
Ian Kent 5ec16e
--- autofs-5.0.6.orig/modules/replicated.c
Ian Kent 5ec16e
+++ autofs-5.0.6/modules/replicated.c
Ian Kent 5ec16e
@@ -563,7 +563,9 @@ static unsigned int get_nfs_info(unsigne
Ian Kent 5ec16e
 		status = rpc_udp_getclient(rpc_info, NFS_PROGRAM, NFS4_VERSION);
Ian Kent 5ec16e
 	else
Ian Kent 5ec16e
 		status = rpc_tcp_getclient(rpc_info, NFS_PROGRAM, NFS4_VERSION);
Ian Kent 5ec16e
-	if (!status) {
Ian Kent 5ec16e
+	if (status == -EHOSTUNREACH)
Ian Kent 5ec16e
+		return (unsigned int) status;
Ian Kent 5ec16e
+	else if (!status) {
Ian Kent 5ec16e
 		gettimeofday(&start, &tz;;
Ian Kent 5ec16e
 		status = rpc_ping_proto(rpc_info);
Ian Kent 5ec16e
 		gettimeofday(&end, &tz;;
Ian Kent 5ec16e
@@ -589,7 +591,10 @@ v3_ver:
Ian Kent 5ec16e
 		status = rpc_portmap_getclient(pm_info,
Ian Kent 5ec16e
 				host->name, host->addr, host->addr_len,
Ian Kent 5ec16e
 				proto, RPC_CLOSE_DEFAULT);
Ian Kent 5ec16e
-		if (status)
Ian Kent 5ec16e
+		if (status == -EHOSTUNREACH) {
Ian Kent 5ec16e
+			supported = status;
Ian Kent 5ec16e
+			goto done_ver;
Ian Kent 5ec16e
+		} else if (status)
Ian Kent 5ec16e
 			goto done_ver;
Ian Kent 5ec16e
 	}
Ian Kent 5ec16e
 
Ian Kent 5ec16e
@@ -602,16 +607,23 @@ v3_ver:
Ian Kent 5ec16e
 	} else {
Ian Kent 5ec16e
 		parms.pm_prot = rpc_info->proto->p_proto;
Ian Kent 5ec16e
 		parms.pm_vers = NFS3_VERSION;
Ian Kent 5ec16e
-		rpc_info->port = rpc_portmap_getport(pm_info, &parms);
Ian Kent 5ec16e
-		if (rpc_info->port < 0)
Ian Kent 5ec16e
+		status = rpc_portmap_getport(pm_info, &parms);
Ian Kent 5ec16e
+		if (status == -EHOSTUNREACH) {
Ian Kent 5ec16e
+			supported = status;
Ian Kent 5ec16e
+			goto done_ver;
Ian Kent 5ec16e
+		} else if (status < 0)
Ian Kent 5ec16e
 			goto v2_ver;
Ian Kent 5ec16e
+		rpc_info->port = status;
Ian Kent 5ec16e
 	}
Ian Kent 5ec16e
 
Ian Kent 5ec16e
 	if (rpc_info->proto->p_proto == IPPROTO_UDP)
Ian Kent 5ec16e
 		status = rpc_udp_getclient(rpc_info, NFS_PROGRAM, NFS3_VERSION);
Ian Kent 5ec16e
 	else
Ian Kent 5ec16e
 		status = rpc_tcp_getclient(rpc_info, NFS_PROGRAM, NFS3_VERSION);
Ian Kent 5ec16e
-	if (!status) {
Ian Kent 5ec16e
+	if (status == -EHOSTUNREACH) {
Ian Kent 5ec16e
+		supported = status;
Ian Kent 5ec16e
+		goto done_ver;
Ian Kent 5ec16e
+	} else if (!status) {
Ian Kent 5ec16e
 		gettimeofday(&start, &tz;;
Ian Kent 5ec16e
 		status = rpc_ping_proto(rpc_info);
Ian Kent 5ec16e
 		gettimeofday(&end, &tz;;
Ian Kent 5ec16e
@@ -643,15 +655,23 @@ v2_ver:
Ian Kent 5ec16e
 		parms.pm_prot = rpc_info->proto->p_proto;
Ian Kent 5ec16e
 		parms.pm_vers = NFS2_VERSION;
Ian Kent 5ec16e
 		rpc_info->port = rpc_portmap_getport(pm_info, &parms);
Ian Kent 5ec16e
-		if (rpc_info->port < 0)
Ian Kent 5ec16e
+		status = rpc_portmap_getport(pm_info, &parms);
Ian Kent 5ec16e
+		if (status == -EHOSTUNREACH) {
Ian Kent 5ec16e
+			supported = status;
Ian Kent 5ec16e
+			goto done_ver;
Ian Kent 5ec16e
+		} else if (status < 0)
Ian Kent 5ec16e
 			goto done_ver;
Ian Kent 5ec16e
+		rpc_info->port = status;
Ian Kent 5ec16e
 	}
Ian Kent 5ec16e
 
Ian Kent 5ec16e
 	if (rpc_info->proto->p_proto == IPPROTO_UDP)
Ian Kent 5ec16e
 		status = rpc_udp_getclient(rpc_info, NFS_PROGRAM, NFS2_VERSION);
Ian Kent 5ec16e
 	else
Ian Kent 5ec16e
 		status = rpc_tcp_getclient(rpc_info, NFS_PROGRAM, NFS2_VERSION);
Ian Kent 5ec16e
-	if (!status) {
Ian Kent 5ec16e
+	if (status == -EHOSTUNREACH) {
Ian Kent 5ec16e
+		supported = status;
Ian Kent 5ec16e
+		goto done_ver;
Ian Kent 5ec16e
+	} else if (!status) {
Ian Kent 5ec16e
 		gettimeofday(&start, &tz;;
Ian Kent 5ec16e
 		status = rpc_ping_proto(rpc_info);
Ian Kent 5ec16e
 		gettimeofday(&end, &tz;;
Ian Kent 5ec16e
@@ -728,21 +748,24 @@ static int get_vers_and_cost(unsigned lo
Ian Kent 5ec16e
 
Ian Kent 5ec16e
 	vers &= version;
Ian Kent 5ec16e
 
Ian Kent 5ec16e
-	if (version & UDP_REQUESTED) {
Ian Kent 5ec16e
+	if (version & TCP_REQUESTED) {
Ian Kent 5ec16e
 		supported = get_nfs_info(logopt, host,
Ian Kent 5ec16e
-				   &pm_info, &rpc_info, "udp", vers, options);
Ian Kent 5ec16e
-		if (supported) {
Ian Kent 5ec16e
+				   &pm_info, &rpc_info, "tcp", vers, options);
Ian Kent 5ec16e
+		if (IS_ERR(supported)) {
Ian Kent 5ec16e
+			if (ERR(supported) == EHOSTUNREACH)
Ian Kent 5ec16e
+				return ret;
Ian Kent 5ec16e
+		} else if (supported) {
Ian Kent 5ec16e
 			ret = 1;
Ian Kent 5ec16e
-			host->version |= (supported << 8);
Ian Kent 5ec16e
+			host->version |= supported;
Ian Kent 5ec16e
 		}
Ian Kent 5ec16e
 	}
Ian Kent 5ec16e
 
Ian Kent 5ec16e
-	if (version & TCP_REQUESTED) {
Ian Kent 5ec16e
+	if (version & UDP_REQUESTED) {
Ian Kent 5ec16e
 		supported = get_nfs_info(logopt, host,
Ian Kent 5ec16e
-				   &pm_info, &rpc_info, "tcp", vers, options);
Ian Kent 5ec16e
+				   &pm_info, &rpc_info, "udp", vers, options);
Ian Kent 5ec16e
 		if (supported) {
Ian Kent 5ec16e
 			ret = 1;
Ian Kent 5ec16e
-			host->version |= supported;
Ian Kent 5ec16e
+			host->version |= (supported << 8);
Ian Kent 5ec16e
 		}
Ian Kent 5ec16e
 	}
Ian Kent 5ec16e
 
Ian Kent 5ec16e
@@ -848,7 +871,9 @@ static int get_supported_ver_and_cost(un
Ian Kent 5ec16e
 		status = rpc_udp_getclient(&rpc_info, NFS_PROGRAM, parms.pm_vers);
Ian Kent 5ec16e
 	else
Ian Kent 5ec16e
 		status = rpc_tcp_getclient(&rpc_info, NFS_PROGRAM, parms.pm_vers);
Ian Kent 5ec16e
-	if (!status) {
Ian Kent 5ec16e
+	if (status == -EHOSTUNREACH)
Ian Kent 5ec16e
+		goto done;
Ian Kent 5ec16e
+	else if (!status) {
Ian Kent 5ec16e
 		gettimeofday(&start, &tz;;
Ian Kent 5ec16e
 		status = rpc_ping_proto(&rpc_info);
Ian Kent 5ec16e
 		gettimeofday(&end, &tz;;