On Mon, Oct 29, 2012 at 11:36 AM, Leonardo Chiquitto <leonardo.lists@xxxxxxxxx> wrote: > 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) Hello Ian, What about this patch, do you think it can be committed? Thanks, Leonardo -- 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