On Mon, Oct 29, 2012 at 12:14 AM, Ian Kent <raven@xxxxxxxxxx> wrote: > On Mon, 2012-10-29 at 09:34 +0800, Ian Kent wrote: >> > >> > * Triggering the mounts simultaneously is required to reproduce the >> > problem, which >> > makes me think if something here (libtirpc for example) is not >> > really thread safe >> > or if the RPC clients must be destroyed after every use to avoid such issues. >> >> Don't think so, it's more likely I'm using a structure obtained from a >> non-reentrant library call. > > Yeah, getprotobyname(3) isn't re-entrant, that's likely the problem. Thanks, Ian. Indeed this is the problem. Instead of using the reentrant version, I think it's better to just get rid of getprotobyname(). The only field from the protoent structure that is used at the moment is the protocol ID. I think it's much easier to just use the ID directly: Index: autofs/include/rpc_subs.h =================================================================== --- autofs.orig/include/rpc_subs.h +++ autofs/include/rpc_subs.h @@ -54,7 +54,7 @@ struct conn_info { unsigned short port; unsigned long program; unsigned long version; - struct protoent *proto; + int proto; unsigned int send_sz; unsigned int recv_sz; struct timeval timeout; @@ -66,7 +66,7 @@ int rpc_udp_getclient(struct conn_info * void rpc_destroy_udp_client(struct conn_info *); 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); +int rpc_portmap_getclient(struct conn_info *, const char *, struct sockaddr *, size_t, int, unsigned int); 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); Index: autofs/modules/replicated.c =================================================================== --- autofs.orig/modules/replicated.c +++ autofs/modules/replicated.c @@ -423,7 +423,7 @@ void free_host_list(struct host **list) static unsigned int get_nfs_info(unsigned logopt, struct host *host, struct conn_info *pm_info, struct conn_info *rpc_info, - const char *proto, unsigned int version, int port) + int proto, unsigned int version, int port) { unsigned int random_selection = host->options & MOUNT_FLAG_RANDOM_SELECT; unsigned int use_weight_only = host->options & MOUNT_FLAG_USE_WEIGHT_ONLY; @@ -437,22 +437,18 @@ static unsigned int get_nfs_info(unsigne int status, count = 0; if (host->addr) - debug(logopt, "called with host %s(%s) proto %s version 0x%x", + debug(logopt, "called with host %s(%s) proto %d version 0x%x", host->name, get_addr_string(host->addr, buf, len), proto, version); else debug(logopt, - "called for host %s proto %s version 0x%x", + "called for host %s proto %d version 0x%x", host->name, proto, version); - rpc_info->proto = getprotobyname(proto); - if (!rpc_info->proto) - return 0; - + rpc_info->proto = proto; memset(&parms, 0, sizeof(struct pmap)); - parms.pm_prog = NFS_PROGRAM; - parms.pm_prot = rpc_info->proto->p_proto; + parms.pm_prot = proto; if (!(version & NFS4_REQUESTED)) goto v3_ver; @@ -483,7 +479,7 @@ static unsigned int get_nfs_info(unsigne } } - if (rpc_info->proto->p_proto == IPPROTO_UDP) + if (rpc_info->proto == IPPROTO_UDP) status = rpc_udp_getclient(rpc_info, NFS_PROGRAM, NFS4_VERSION); else status = rpc_tcp_getclient(rpc_info, NFS_PROGRAM, NFS4_VERSION); @@ -544,7 +540,7 @@ v3_ver: goto v2_ver; } - if (rpc_info->proto->p_proto == IPPROTO_UDP) + if (rpc_info->proto == IPPROTO_UDP) status = rpc_udp_getclient(rpc_info, NFS_PROGRAM, NFS3_VERSION); else status = rpc_tcp_getclient(rpc_info, NFS_PROGRAM, NFS3_VERSION); @@ -591,7 +587,7 @@ v2_ver: goto done_ver; } - if (rpc_info->proto->p_proto == IPPROTO_UDP) + if (rpc_info->proto == IPPROTO_UDP) status = rpc_udp_getclient(rpc_info, NFS_PROGRAM, NFS2_VERSION); else status = rpc_tcp_getclient(rpc_info, NFS_PROGRAM, NFS2_VERSION); @@ -622,7 +618,7 @@ v2_ver: } done_ver: - if (rpc_info->proto->p_proto == IPPROTO_UDP) { + if (rpc_info->proto == IPPROTO_UDP) { rpc_destroy_udp_client(rpc_info); rpc_destroy_udp_client(pm_info); } else { @@ -679,7 +675,7 @@ static int get_vers_and_cost(unsigned lo if (version & TCP_REQUESTED) { supported = get_nfs_info(logopt, host, - &pm_info, &rpc_info, "tcp", vers, port); + &pm_info, &rpc_info, IPPROTO_TCP, vers, port); if (IS_ERR(supported)) { if (ERR(supported) == EHOSTUNREACH || ERR(supported) == ETIMEDOUT) @@ -692,7 +688,7 @@ static int get_vers_and_cost(unsigned lo if (version & UDP_REQUESTED) { supported = get_nfs_info(logopt, host, - &pm_info, &rpc_info, "udp", vers, port); + &pm_info, &rpc_info, IPPROTO_UDP, vers, port); if (IS_ERR(supported)) { if (!ret && ERR(supported) == ETIMEDOUT) return ret; @@ -713,7 +709,7 @@ static int get_supported_ver_and_cost(un socklen_t len = INET6_ADDRSTRLEN; char buf[len + 1]; struct conn_info pm_info, rpc_info; - const char *proto; + int proto; unsigned int vers; struct timeval start, end; struct timezone tz; @@ -752,10 +748,10 @@ static int get_supported_ver_and_cost(un * So, we do the conversion here. */ if (version & UDP_SELECTED_MASK) { - proto = "udp"; + proto = IPPROTO_UDP; version >>= 8; } else - proto = "tcp"; + proto = IPPROTO_TCP; switch (version) { case NFS2_SUPPORTED: @@ -772,9 +768,7 @@ static int get_supported_ver_and_cost(un return 0; } - rpc_info.proto = getprotobyname(proto); - if (!rpc_info.proto) - return 0; + rpc_info.proto = proto; if (port > 0) rpc_info.port = port; @@ -790,14 +784,14 @@ static int get_supported_ver_and_cost(un memset(&parms, 0, sizeof(struct pmap)); parms.pm_prog = NFS_PROGRAM; - parms.pm_prot = rpc_info.proto->p_proto; + parms.pm_prot = rpc_info.proto; parms.pm_vers = vers; ret = rpc_portmap_getport(&pm_info, &parms, &rpc_info.port); if (ret < 0) goto done; } - if (rpc_info.proto->p_proto == IPPROTO_UDP) + if (rpc_info.proto == IPPROTO_UDP) status = rpc_udp_getclient(&rpc_info, NFS_PROGRAM, vers); else status = rpc_tcp_getclient(&rpc_info, NFS_PROGRAM, vers); @@ -819,7 +813,7 @@ static int get_supported_ver_and_cost(un } } done: - if (rpc_info.proto->p_proto == IPPROTO_UDP) { + if (rpc_info.proto == IPPROTO_UDP) { rpc_destroy_udp_client(&rpc_info); rpc_destroy_udp_client(&pm_info); } else { Index: autofs/lib/rpc_subs.c =================================================================== --- autofs.orig/lib/rpc_subs.c +++ autofs/lib/rpc_subs.c @@ -160,7 +160,7 @@ static int rpc_do_create_client(struct s *client = NULL; - proto = info->proto->p_proto; + proto = info->proto; if (proto == IPPROTO_UDP) type = SOCK_DGRAM; else @@ -191,7 +191,7 @@ static int rpc_do_create_client(struct s in4_raddr = (struct sockaddr_in *) addr; in4_raddr->sin_port = htons(info->port); - switch (info->proto->p_proto) { + switch (info->proto) { case IPPROTO_UDP: clnt = clntudp_bufcreate(in4_raddr, info->program, info->version, @@ -231,7 +231,7 @@ static int rpc_do_create_client(struct s *client = NULL; - proto = info->proto->p_proto; + proto = info->proto; if (proto == IPPROTO_UDP) type = SOCK_DGRAM; else @@ -282,11 +282,11 @@ 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_UDP) + if (info->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) { + else if (info->proto == IPPROTO_TCP) { ret = connect_nb(*fd, addr, slen, &info->timeout); if (ret < 0) return ret; @@ -345,7 +345,7 @@ static int create_client(struct conn_inf memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_ADDRCONFIG; hints.ai_family = AF_UNSPEC; - if (info->proto->p_proto == IPPROTO_UDP) + if (info->proto == IPPROTO_UDP) hints.ai_socktype = SOCK_DGRAM; else hints.ai_socktype = SOCK_STREAM; @@ -360,7 +360,7 @@ static int create_client(struct conn_inf haddr = ai; while (haddr) { - if (haddr->ai_protocol != info->proto->p_proto) { + if (haddr->ai_protocol != info->proto) { haddr = haddr->ai_next; continue; } @@ -407,16 +407,11 @@ out_close: int rpc_udp_getclient(struct conn_info *info, unsigned int program, unsigned int version) { - struct protoent *pe_proto; CLIENT *client; int ret; if (!info->client) { - pe_proto = getprotobyname("udp"); - if (!pe_proto) - return -ENOENT; - - info->proto = pe_proto; + info->proto = IPPROTO_UDP; info->timeout.tv_sec = RPC_TOUT_UDP; info->timeout.tv_usec = 0; info->send_sz = UDPMSGSIZE; @@ -448,16 +443,11 @@ void rpc_destroy_udp_client(struct conn_ int rpc_tcp_getclient(struct conn_info *info, unsigned int program, unsigned int version) { - struct protoent *pe_proto; CLIENT *client; int ret; if (!info->client) { - pe_proto = getprotobyname("tcp"); - if (!pe_proto) - return -ENOENT; - - info->proto = pe_proto; + info->proto = IPPROTO_TCP; info->timeout.tv_sec = RPC_TOUT_TCP; info->timeout.tv_usec = 0; info->send_sz = 0; @@ -503,23 +493,18 @@ void rpc_destroy_tcp_client(struct conn_ int rpc_portmap_getclient(struct conn_info *info, const char *host, struct sockaddr *addr, size_t addr_len, - const char *proto, unsigned int option) + int proto, unsigned int option) { - struct protoent *pe_proto; CLIENT *client; int ret; - pe_proto = getprotobyname(proto); - if (!pe_proto) - return -ENOENT; - info->host = host; info->addr = addr; info->addr_len = addr_len; info->program = PMAPPROG; info->port = PMAPPORT; info->version = PMAPVERS; - info->proto = pe_proto; + info->proto = proto; info->send_sz = RPCSMALLMSGSIZE; info->recv_sz = RPCSMALLMSGSIZE; info->timeout.tv_sec = PMAP_TOUT_UDP; @@ -527,7 +512,7 @@ int rpc_portmap_getclient(struct conn_in info->close_option = option; info->client = NULL; - if (pe_proto->p_proto == IPPROTO_TCP) + if (info->proto == IPPROTO_TCP) info->timeout.tv_sec = PMAP_TOUT_TCP; ret = create_client(info, &client); @@ -545,7 +530,7 @@ int rpc_portmap_getport(struct conn_info struct conn_info pmap_info; CLIENT *client; enum clnt_stat status; - int proto = info->proto->p_proto; + int proto = info->proto; int ret; memset(&pmap_info, 0, sizeof(struct conn_info)); @@ -623,13 +608,13 @@ int rpc_ping_proto(struct conn_info *inf { CLIENT *client; enum clnt_stat status; - int proto = info->proto->p_proto; + int proto = info->proto; int ret; if (info->client) client = info->client; else { - if (info->proto->p_proto == IPPROTO_UDP) { + if (info->proto == IPPROTO_UDP) { info->send_sz = UDPMSGSIZE; info->recv_sz = UDPMSGSIZE; } @@ -678,7 +663,7 @@ int rpc_ping_proto(struct conn_info *inf static unsigned int __rpc_ping(const char *host, unsigned long version, - char *proto, + int proto, long seconds, long micros, unsigned int option) { @@ -686,6 +671,7 @@ static unsigned int __rpc_ping(const cha struct conn_info info; struct pmap parms; + info.proto = proto; info.host = host; info.addr = NULL; info.addr_len = 0; @@ -700,13 +686,9 @@ static unsigned int __rpc_ping(const cha status = RPC_PING_FAIL; - info.proto = getprotobyname(proto); - if (!info.proto) - return status; - parms.pm_prog = NFS_PROGRAM; parms.pm_vers = version; - parms.pm_prot = info.proto->p_proto; + parms.pm_prot = info.proto; parms.pm_port = 0; status = rpc_portmap_getport(&info, &parms, &info.port); @@ -724,19 +706,19 @@ int rpc_ping(const char *host, long seco unsigned long vers2 = NFS2_VERSION; unsigned int status; - status = __rpc_ping(host, vers2, "udp", seconds, micros, option); + status = __rpc_ping(host, vers2, IPPROTO_UDP, seconds, micros, option); if (status > 0) return RPC_PING_V2 | RPC_PING_UDP; - status = __rpc_ping(host, vers3, "udp", seconds, micros, option); + status = __rpc_ping(host, vers3, IPPROTO_UDP, seconds, micros, option); if (status > 0) return RPC_PING_V3 | RPC_PING_UDP; - status = __rpc_ping(host, vers2, "tcp", seconds, micros, option); + status = __rpc_ping(host, vers2, IPPROTO_TCP, seconds, micros, option); if (status > 0) return RPC_PING_V2 | RPC_PING_TCP; - status = __rpc_ping(host, vers3, "tcp", seconds, micros, option); + status = __rpc_ping(host, vers3, IPPROTO_TCP, seconds, micros, option); if (status > 0) return RPC_PING_V3 | RPC_PING_TCP; @@ -759,11 +741,10 @@ int rpc_time(const char *host, double taken; struct timeval start, end; struct timezone tz; - char *proto = (ping_proto & RPC_PING_UDP) ? "udp" : "tcp"; unsigned long vers = ping_vers; gettimeofday(&start, &tz); - status = __rpc_ping(host, vers, proto, seconds, micros, option); + status = __rpc_ping(host, vers, ping_proto, seconds, micros, option); gettimeofday(&end, &tz); if (status == RPC_PING_FAIL || status < 0) @@ -781,12 +762,12 @@ static int rpc_get_exports_proto(struct { CLIENT *client; enum clnt_stat status; - int proto = info->proto->p_proto; + int proto = info->proto; unsigned int option = info->close_option; int vers_entry; int ret; - if (info->proto->p_proto == IPPROTO_UDP) { + if (info->proto == IPPROTO_UDP) { info->send_sz = UDPMSGSIZE; info->recv_sz = UDPMSGSIZE; } @@ -893,11 +874,9 @@ exports rpc_get_exports(const char *host parms.pm_port = 0; /* Try UDP first */ - info.proto = getprotobyname("udp"); - if (!info.proto) - goto try_tcp; + info.proto = IPPROTO_UDP; - parms.pm_prot = info.proto->p_proto; + parms.pm_prot = info.proto; status = rpc_portmap_getport(&info, &parms, &info.port); if (status < 0) @@ -910,11 +889,9 @@ exports rpc_get_exports(const char *host return exportlist; try_tcp: - info.proto = getprotobyname("tcp"); - if (!info.proto) - return NULL; + info.proto = IPPROTO_TCP; - parms.pm_prot = info.proto->p_proto; + parms.pm_prot = info.proto; status = rpc_portmap_getport(&info, &parms, &info.port); if (status < 0) -- To unsubscribe from this list: send the line "unsubscribe autofs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html