Re: Concurrency problem when triggering many mounts simultaneously

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, 2013-01-04 at 15:25 -0200, Leonardo Chiquitto wrote:
> 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?

Yep, I think this is the best thing to do. I can't find the original
message which has the patch and this message has all sorts of wrap going
on. Could you send the patch again please.

> 
> 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


--
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


[Index of Archives]     [Linux Filesystem Development]     [Linux Ext4]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux