autofs-5.0.6 - catch EHOSTUNREACH and bail out early From: Ian Kent 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(-) diff --git a/CHANGELOG b/CHANGELOG index c581099..69ade49 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -31,6 +31,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 ----------------------- diff --git a/include/replicated.h b/include/replicated.h index 206918e..a143ccf 100644 --- a/include/replicated.h +++ b/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 { diff --git a/modules/replicated.c b/modules/replicated.c index ab8fdf3..e14c5da 100644 --- a/modules/replicated.c +++ b/modules/replicated.c @@ -563,7 +563,9 @@ static unsigned int get_nfs_info(unsigned logopt, struct host *host, 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 logopt, struct host *host, 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(unsigned logopt, struct host *host, 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);