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(-) --- 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);