diff -Nur autofs-4.1.3.orig/include/automount.h autofs-4.1.3/include/automount.h --- autofs-4.1.3.orig/include/automount.h 2004-05-16 12:07:10.000000000 +0800 +++ autofs-4.1.3/include/automount.h 2004-05-16 17:36:38.000000000 +0800 @@ -241,8 +241,16 @@ const char *dir, const char *base, size_t blen); /* rpc helper subs */ -int rpc_ping(const char *host, long seconds, long micros); -int rpc_time(const char *host, int seconds, int micros, double *result); +#define RPC_PING_FAIL 0x0000 +#define RPC_PING_V2 NFS2_VERSION +#define RPC_PING_V3 NFS3_VERSION +#define RPC_PING_UDP 0x0100 +#define RPC_PING_TCP 0x0200 + +unsigned int rpc_ping(const char *host, long seconds, long micros); +int rpc_time(const char *host, + unsigned int ping_vers, unsigned int ping_proto, + long seconds, long micros, double *result); /* log notification */ extern int do_verbose; diff -Nur autofs-4.1.3.orig/lib/rpc_subs.c autofs-4.1.3/lib/rpc_subs.c --- autofs-4.1.3.orig/lib/rpc_subs.c 2004-05-16 12:07:10.000000000 +0800 +++ autofs-4.1.3/lib/rpc_subs.c 2004-05-16 17:36:38.000000000 +0800 @@ -1,15 +1,20 @@ #include #include #include +#include #include -int rpc_ping(const char *host, long seconds, long micros) +#include "automount.h" + +static int rpc_ping_proto(const char *host, + unsigned long nfs_version, const char *proto, + long seconds, long micros) { CLIENT *client; struct timeval tout; enum clnt_stat stat; - client = clnt_create(host, NFS_PROGRAM, NFS2_VERSION, "udp"); + client = clnt_create(host, NFS_PROGRAM, nfs_version, proto); if (client == NULL) { return 0; } @@ -32,6 +37,49 @@ return 1; } +static unsigned int rpc_ping_v2(const char *host, long seconds, long micros) +{ + unsigned int status = RPC_PING_FAIL; + + status = rpc_ping_proto(host, NFS2_VERSION, "udp", seconds, micros); + if (status) + return RPC_PING_V2 | RPC_PING_UDP; + + status = rpc_ping_proto(host, NFS2_VERSION, "tcp", seconds, micros); + if (status) + return RPC_PING_V2 | RPC_PING_TCP; + + return status; +} + +static unsigned int rpc_ping_v3(const char *host, long seconds, long micros) +{ + unsigned int status = RPC_PING_FAIL; + + status = rpc_ping_proto(host, NFS3_VERSION, "udp", seconds, micros); + if (status) + return RPC_PING_V3 | RPC_PING_UDP; + + status = rpc_ping_proto(host, NFS3_VERSION, "tcp", seconds, micros); + if (status) + return RPC_PING_V3 | RPC_PING_TCP; + + return status; +} + +unsigned int rpc_ping(const char *host, long seconds, long micros) +{ + unsigned int status; + + status = rpc_ping_v2(host, seconds, micros); + if (status) + return status; + + status = rpc_ping_v3(host, seconds, micros); + + return status; +} + static double elapsed(struct timeval start, struct timeval end) { double t1, t2; @@ -40,34 +88,21 @@ return t2-t1; } -int rpc_time(const char *host, int seconds, int micros, double *result) +int rpc_time(const char *host, + unsigned int ping_vers, unsigned int ping_proto, + long seconds, long micros, double *result) { - CLIENT *client; - struct timeval tout; - enum clnt_stat stat; + int status; + double taken; struct timeval start, end; struct timezone tz; - double taken; - - client = clnt_create(host, NFS_PROGRAM, NFS2_VERSION, "udp"); - if (client == NULL) { - return 0; - } - - tout.tv_sec = seconds; - tout.tv_usec = micros; - - clnt_control(client, CLSET_TIMEOUT, (char *)&tout); - clnt_control(client, CLSET_RETRY_TIMEOUT, (char *)&tout); + char *proto = (ping_proto & RPC_PING_UDP) ? "udp" : "tcp"; gettimeofday(&start, &tz); - stat = clnt_call(client, NFSPROC_NULL, - (xdrproc_t)xdr_void, 0, (xdrproc_t)xdr_void, 0, tout); + status = rpc_ping_proto(host, ping_vers, proto, seconds, micros); gettimeofday(&end, &tz); - clnt_destroy(client); - - if (stat != RPC_SUCCESS) { + if (!status) { return 0; } @@ -77,6 +112,6 @@ *result = taken; } - return 1; + return status; } diff -Nur autofs-4.1.3.orig/modules/mount_nfs.c autofs-4.1.3/modules/mount_nfs.c --- autofs-4.1.3.orig/modules/mount_nfs.c 2004-05-16 12:07:10.000000000 +0800 +++ autofs-4.1.3/modules/mount_nfs.c 2004-05-16 17:36:38.000000000 +0800 @@ -29,6 +29,8 @@ #include #include #include +#include +#include #define MODULE_MOUNT #include "automount.h" @@ -139,6 +141,7 @@ while (p && *p) { char *next; + unsigned int ping_stat = 0; p += strspn(p, " \t,"); delim = strpbrk(p, "(, \t:"); @@ -148,7 +151,7 @@ /* Find lowest weight whose server is alive */ if (*delim == '(') { char *weight = delim + 1; - int alive; + unsigned int alive; *delim = '\0'; @@ -217,7 +220,7 @@ * If it's not local and it's a replicated server map entry * is it alive */ - if (!local && is_replicated && !rpc_ping(p, sec, micros)) { + if (!local && is_replicated && !(ping_stat = rpc_ping(p, sec, micros))) { p = next; continue; } @@ -228,18 +231,25 @@ } /* compare RPC times if there are no weighted hosts */ else if (winner_weight == INT_MAX) { + int status; double resp_time; + unsigned int vers = NFS2_VERSION; + unsigned int proto = RPC_PING_UDP; + if (ping_stat) { + vers = ping_stat & 0x00ff; + proto = ping_stat & 0xff00; + } + + status = rpc_time(winner, vers, proto, sec, micros, &resp_time); /* did we time the first winner? */ if (winner_time == 0) { - if (rpc_time(winner, sec, micros, &resp_time)) + if (status) winner_time = resp_time; else winner_time = 6; - } - - if (rpc_time(winner, sec, micros, &resp_time)) { - if (resp_time < winner_time) { + } else { + if ((status) && (resp_time < winner_time)) { winner = p; winner_time = resp_time; }