- fix typo in libtirpc file name. - fix rework error return handling in rpc code. - allow MOUNT_WAIT to override probe. - improve UDP RPC timeout handling. - fix segfault in get_query_dn(). - use strtok_r() in linux_version_code(). - fix sss wildcard match. - fix dlopen() error handling in sss module. - fix configure string length tests for sss library.
373 lines
10 KiB
Diff
373 lines
10 KiB
Diff
autofs-5.0.6 - improve UDP RPC timeout handling
|
|
|
|
From: Ian Kent <ikent@redhat.com>
|
|
|
|
The RPC code still doesn't control timeout quite right. Change that
|
|
to take control of the UDP timeout too.
|
|
---
|
|
|
|
CHANGELOG | 1
|
|
include/rpc_subs.h | 5 ++
|
|
lib/rpc_subs.c | 93 +++++++++++++++++++--------------------------------
|
|
modules/replicated.c | 36 ++++++++++++-------
|
|
4 files changed, 63 insertions(+), 72 deletions(-)
|
|
|
|
|
|
--- autofs-5.0.6.orig/CHANGELOG
|
|
+++ autofs-5.0.6/CHANGELOG
|
|
@@ -35,6 +35,7 @@
|
|
- fix typo in libtirpc file name.
|
|
- fix rework error return handling in rpc code.
|
|
- allow MOUNT_WAIT to override probe.
|
|
+- improve UDP RPC timeout handling.
|
|
|
|
28/06/2011 autofs-5.0.6
|
|
-----------------------
|
|
--- autofs-5.0.6.orig/include/rpc_subs.h
|
|
+++ autofs-5.0.6/include/rpc_subs.h
|
|
@@ -42,6 +42,9 @@
|
|
#define PMAP_TOUT_UDP 3
|
|
#define PMAP_TOUT_TCP 5
|
|
|
|
+#define RPC_TOUT_UDP PMAP_TOUT_UDP
|
|
+#define RPC_TOUT_TCP PMAP_TOUT_TCP
|
|
+
|
|
#define HOST_ENT_BUF_SIZE 2048
|
|
|
|
struct conn_info {
|
|
@@ -64,7 +67,7 @@ void rpc_destroy_udp_client(struct conn_
|
|
int rpc_tcp_getclient(struct conn_info *, unsigned int, unsigned int);
|
|
void rpc_destroy_tcp_client(struct conn_info *);
|
|
int rpc_portmap_getclient(struct conn_info *, const char *, struct sockaddr *, size_t, const char *, unsigned int);
|
|
-unsigned short rpc_portmap_getport(struct conn_info *, struct pmap *);
|
|
+int rpc_portmap_getport(struct conn_info *, struct pmap *, unsigned short *);
|
|
int rpc_ping_proto(struct conn_info *);
|
|
int rpc_ping(const char *, long, long, unsigned int);
|
|
double elapsed(struct timeval, struct timeval);
|
|
--- autofs-5.0.6.orig/lib/rpc_subs.c
|
|
+++ autofs-5.0.6/lib/rpc_subs.c
|
|
@@ -218,43 +218,24 @@ static int rpc_do_create_client(struct s
|
|
return 0;
|
|
}
|
|
#else
|
|
-struct netconfig *find_netconf(void *handle, char *family, char *proto)
|
|
-{
|
|
- struct netconfig *nconf;
|
|
-
|
|
- while ((nconf = getnetconfig(handle))) {
|
|
- if ((strcmp(nconf->nc_protofmly, family) == 0) &&
|
|
- (strcmp(nconf->nc_proto, proto) == 0))
|
|
- break;
|
|
- }
|
|
-
|
|
- return nconf;
|
|
-}
|
|
-
|
|
static int rpc_do_create_client(struct sockaddr *addr, struct conn_info *info, int *fd, CLIENT **client)
|
|
{
|
|
CLIENT *clnt = NULL;
|
|
struct sockaddr_in in4_laddr;
|
|
struct sockaddr_in6 in6_laddr;
|
|
struct sockaddr *laddr = NULL;
|
|
- struct netconfig *nconf;
|
|
struct netbuf nb_addr;
|
|
int type, proto;
|
|
- char *nc_family, *nc_proto;
|
|
- void *handle;
|
|
size_t slen;
|
|
int ret;
|
|
|
|
*client = NULL;
|
|
|
|
proto = info->proto->p_proto;
|
|
- if (proto == IPPROTO_UDP) {
|
|
+ if (proto == IPPROTO_UDP)
|
|
type = SOCK_DGRAM;
|
|
- nc_proto = NC_UDP;
|
|
- } else {
|
|
+ else
|
|
type = SOCK_STREAM;
|
|
- nc_proto = NC_TCP;
|
|
- }
|
|
|
|
/*
|
|
* bind to any unused port. If we left this up to the rpc
|
|
@@ -269,7 +250,6 @@ static int rpc_do_create_client(struct s
|
|
laddr = (struct sockaddr *) &in4_laddr;
|
|
in4_raddr->sin_port = htons(info->port);
|
|
slen = sizeof(struct sockaddr_in);
|
|
- nc_family = NC_INET;
|
|
} else if (addr->sa_family == AF_INET6) {
|
|
struct sockaddr_in6 *in6_raddr = (struct sockaddr_in6 *) addr;
|
|
in6_laddr.sin6_family = AF_INET6;
|
|
@@ -278,20 +258,9 @@ static int rpc_do_create_client(struct s
|
|
laddr = (struct sockaddr *) &in6_laddr;
|
|
in6_raddr->sin6_port = htons(info->port);
|
|
slen = sizeof(struct sockaddr_in6);
|
|
- nc_family = NC_INET6;
|
|
} else
|
|
return -EINVAL;
|
|
|
|
- handle = setnetconfig();
|
|
- if (!handle)
|
|
- return -EINVAL;
|
|
-
|
|
- nconf = find_netconf(handle, nc_family, nc_proto);
|
|
- if (!nconf) {
|
|
- endnetconfig(handle);
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
/*
|
|
* bind to any unused port. If we left this up to the rpc layer,
|
|
* it would bind to a reserved port, which has been shown to
|
|
@@ -301,13 +270,11 @@ static int rpc_do_create_client(struct s
|
|
*fd = open_sock(addr->sa_family, type, proto);
|
|
if (*fd < 0) {
|
|
ret = -errno;
|
|
- endnetconfig(handle);
|
|
return ret;
|
|
}
|
|
|
|
if (bind(*fd, laddr, slen) < 0) {
|
|
ret = -errno;
|
|
- endnetconfig(handle);
|
|
return ret;
|
|
}
|
|
}
|
|
@@ -315,19 +282,23 @@ static int rpc_do_create_client(struct s
|
|
nb_addr.maxlen = nb_addr.len = slen;
|
|
nb_addr.buf = addr;
|
|
|
|
- if (info->proto->p_proto == IPPROTO_TCP) {
|
|
+ if (info->proto->p_proto == IPPROTO_UDP)
|
|
+ clnt = clnt_dg_create(*fd, &nb_addr,
|
|
+ info->program, info->version,
|
|
+ info->send_sz, info->recv_sz);
|
|
+ else if (info->proto->p_proto == IPPROTO_TCP) {
|
|
ret = connect_nb(*fd, addr, slen, &info->timeout);
|
|
- if (ret < 0) {
|
|
- endnetconfig(handle);
|
|
+ if (ret < 0)
|
|
return ret;
|
|
- }
|
|
- }
|
|
-
|
|
- clnt = clnt_tli_create(*fd, nconf, &nb_addr,
|
|
- info->program, info->version,
|
|
- info->send_sz, info->recv_sz);
|
|
+ clnt = clnt_vc_create(*fd, &nb_addr,
|
|
+ info->program, info->version,
|
|
+ info->send_sz, info->recv_sz);
|
|
+ } else
|
|
+ return -EINVAL;
|
|
|
|
- endnetconfig(handle);
|
|
+ /* Our timeout is in seconds */
|
|
+ if (clnt && info->timeout.tv_sec)
|
|
+ clnt_control(clnt, CLSET_TIMEOUT, (void *) &info->timeout);
|
|
|
|
*client = clnt;
|
|
|
|
@@ -441,6 +412,8 @@ int rpc_udp_getclient(struct conn_info *
|
|
return -ENOENT;
|
|
|
|
info->proto = pe_proto;
|
|
+ info->timeout.tv_sec = RPC_TOUT_UDP;
|
|
+ info->timeout.tv_usec = 0;
|
|
info->send_sz = UDPMSGSIZE;
|
|
info->recv_sz = UDPMSGSIZE;
|
|
}
|
|
@@ -480,6 +453,8 @@ int rpc_tcp_getclient(struct conn_info *
|
|
return -ENOENT;
|
|
|
|
info->proto = pe_proto;
|
|
+ info->timeout.tv_sec = RPC_TOUT_TCP;
|
|
+ info->timeout.tv_usec = 0;
|
|
info->send_sz = 0;
|
|
info->recv_sz = 0;
|
|
}
|
|
@@ -559,10 +534,10 @@ int rpc_portmap_getclient(struct conn_in
|
|
return 0;
|
|
}
|
|
|
|
-unsigned short rpc_portmap_getport(struct conn_info *info, struct pmap *parms)
|
|
+int rpc_portmap_getport(struct conn_info *info,
|
|
+ struct pmap *parms, unsigned short *port)
|
|
{
|
|
struct conn_info pmap_info;
|
|
- unsigned short port = 0;
|
|
CLIENT *client;
|
|
enum clnt_stat status;
|
|
int proto = info->proto->p_proto;
|
|
@@ -604,7 +579,7 @@ unsigned short rpc_portmap_getport(struc
|
|
if (status == RPC_SUCCESS) {
|
|
status = clnt_call(client, PMAPPROC_GETPORT,
|
|
(xdrproc_t) xdr_pmap, (caddr_t) parms,
|
|
- (xdrproc_t) xdr_u_short, (caddr_t) &port,
|
|
+ (xdrproc_t) xdr_u_short, (caddr_t) port,
|
|
pmap_info.timeout);
|
|
}
|
|
|
|
@@ -631,10 +606,12 @@ unsigned short rpc_portmap_getport(struc
|
|
clnt_destroy(client);
|
|
}
|
|
|
|
- if (status != RPC_SUCCESS)
|
|
+ if (status == RPC_TIMEDOUT)
|
|
+ return -ETIMEDOUT;
|
|
+ else if (status != RPC_SUCCESS)
|
|
return -EIO;
|
|
|
|
- return port;
|
|
+ return 0;
|
|
}
|
|
|
|
int rpc_ping_proto(struct conn_info *info)
|
|
@@ -686,7 +663,9 @@ int rpc_ping_proto(struct conn_info *inf
|
|
clnt_destroy(client);
|
|
}
|
|
|
|
- if (status != RPC_SUCCESS)
|
|
+ if (status == RPC_TIMEDOUT)
|
|
+ return -ETIMEDOUT;
|
|
+ else if (status != RPC_SUCCESS)
|
|
return -EIO;
|
|
|
|
return 1;
|
|
@@ -725,8 +704,8 @@ static unsigned int __rpc_ping(const cha
|
|
parms.pm_prot = info.proto->p_proto;
|
|
parms.pm_port = 0;
|
|
|
|
- info.port = rpc_portmap_getport(&info, &parms);
|
|
- if (info.port < 0)
|
|
+ status = rpc_portmap_getport(&info, &parms, &info.port);
|
|
+ if (status < 0)
|
|
return status;
|
|
|
|
status = rpc_ping_proto(&info);
|
|
@@ -915,8 +894,8 @@ exports rpc_get_exports(const char *host
|
|
|
|
parms.pm_prot = info.proto->p_proto;
|
|
|
|
- info.port = rpc_portmap_getport(&info, &parms);
|
|
- if (info.port < 0)
|
|
+ status = rpc_portmap_getport(&info, &parms, &info.port);
|
|
+ if (status < 0)
|
|
goto try_tcp;
|
|
|
|
memset(&exportlist, '\0', sizeof(exportlist));
|
|
@@ -932,8 +911,8 @@ try_tcp:
|
|
|
|
parms.pm_prot = info.proto->p_proto;
|
|
|
|
- info.port = rpc_portmap_getport(&info, &parms);
|
|
- if (info.port < 0)
|
|
+ status = rpc_portmap_getport(&info, &parms, &info.port);
|
|
+ if (status < 0)
|
|
return NULL;
|
|
|
|
memset(&exportlist, '\0', sizeof(exportlist));
|
|
--- autofs-5.0.6.orig/modules/replicated.c
|
|
+++ autofs-5.0.6/modules/replicated.c
|
|
@@ -569,7 +569,9 @@ static unsigned int get_nfs_info(unsigne
|
|
gettimeofday(&start, &tz);
|
|
status = rpc_ping_proto(rpc_info);
|
|
gettimeofday(&end, &tz);
|
|
- if (status > 0) {
|
|
+ if (status == -ETIMEDOUT)
|
|
+ return (unsigned int) status;
|
|
+ else if (status > 0) {
|
|
double reply;
|
|
if (random_selection) {
|
|
/* Random value between 0 and 1 */
|
|
@@ -607,13 +609,12 @@ v3_ver:
|
|
} else {
|
|
parms.pm_prot = rpc_info->proto->p_proto;
|
|
parms.pm_vers = NFS3_VERSION;
|
|
- status = rpc_portmap_getport(pm_info, &parms);
|
|
- if (status == -EHOSTUNREACH) {
|
|
+ status = rpc_portmap_getport(pm_info, &parms, &rpc_info->port);
|
|
+ if (status == -EHOSTUNREACH || status == -ETIMEDOUT) {
|
|
supported = status;
|
|
goto done_ver;
|
|
} else if (status < 0)
|
|
goto v2_ver;
|
|
- rpc_info->port = status;
|
|
}
|
|
|
|
if (rpc_info->proto->p_proto == IPPROTO_UDP)
|
|
@@ -627,7 +628,10 @@ v3_ver:
|
|
gettimeofday(&start, &tz);
|
|
status = rpc_ping_proto(rpc_info);
|
|
gettimeofday(&end, &tz);
|
|
- if (status > 0) {
|
|
+ if (status == -ETIMEDOUT) {
|
|
+ supported = status;
|
|
+ goto done_ver;
|
|
+ } else if (status > 0) {
|
|
double reply;
|
|
if (random_selection) {
|
|
/* Random value between 0 and 1 */
|
|
@@ -654,14 +658,12 @@ v2_ver:
|
|
} else {
|
|
parms.pm_prot = rpc_info->proto->p_proto;
|
|
parms.pm_vers = NFS2_VERSION;
|
|
- rpc_info->port = rpc_portmap_getport(pm_info, &parms);
|
|
- status = rpc_portmap_getport(pm_info, &parms);
|
|
- if (status == -EHOSTUNREACH) {
|
|
+ status = rpc_portmap_getport(pm_info, &parms, &rpc_info->port);
|
|
+ if (status == -EHOSTUNREACH || status == -ETIMEDOUT) {
|
|
supported = status;
|
|
goto done_ver;
|
|
} else if (status < 0)
|
|
goto done_ver;
|
|
- rpc_info->port = status;
|
|
}
|
|
|
|
if (rpc_info->proto->p_proto == IPPROTO_UDP)
|
|
@@ -675,7 +677,9 @@ v2_ver:
|
|
gettimeofday(&start, &tz);
|
|
status = rpc_ping_proto(rpc_info);
|
|
gettimeofday(&end, &tz);
|
|
- if (status > 0) {
|
|
+ if (status == -ETIMEDOUT)
|
|
+ supported = status;
|
|
+ else if (status > 0) {
|
|
double reply;
|
|
if (random_selection) {
|
|
/* Random value between 0 and 1 */
|
|
@@ -752,7 +756,8 @@ static int get_vers_and_cost(unsigned lo
|
|
supported = get_nfs_info(logopt, host,
|
|
&pm_info, &rpc_info, "tcp", vers, options);
|
|
if (IS_ERR(supported)) {
|
|
- if (ERR(supported) == EHOSTUNREACH)
|
|
+ if (ERR(supported) == EHOSTUNREACH ||
|
|
+ ERR(supported) == ETIMEDOUT)
|
|
return ret;
|
|
} else if (supported) {
|
|
ret = 1;
|
|
@@ -763,7 +768,10 @@ static int get_vers_and_cost(unsigned lo
|
|
if (version & UDP_REQUESTED) {
|
|
supported = get_nfs_info(logopt, host,
|
|
&pm_info, &rpc_info, "udp", vers, options);
|
|
- if (supported) {
|
|
+ if (IS_ERR(supported)) {
|
|
+ if (ERR(supported) == ETIMEDOUT)
|
|
+ return ret;
|
|
+ } else if (supported) {
|
|
ret = 1;
|
|
host->version |= (supported << 8);
|
|
}
|
|
@@ -862,8 +870,8 @@ static int get_supported_ver_and_cost(un
|
|
return 0;
|
|
|
|
parms.pm_prot = rpc_info.proto->p_proto;
|
|
- rpc_info.port = rpc_portmap_getport(&pm_info, &parms);
|
|
- if (rpc_info.port < 0)
|
|
+ ret = rpc_portmap_getport(&pm_info, &parms, &rpc_info.port);
|
|
+ if (ret < 0)
|
|
goto done;
|
|
}
|
|
|