SUNRPC/NFSD: Support a new option for ignoring the result of svc_register
authorKinglong Mee <kinglongmee@gmail.com>
Tue, 31 Dec 2013 05:17:20 +0000 (13:17 +0800)
committerJ. Bruce Fields <bfields@redhat.com>
Fri, 3 Jan 2014 23:18:49 +0000 (18:18 -0500)
NFSv4 clients can contact port 2049 directly instead of needing the
portmapper.

Therefore a failure to register to the portmapper when starting an
NFSv4-only server isn't really a problem.

But Gareth Williams reports that an attempt to start an NFSv4-only
server without starting portmap fails:

  #rpc.nfsd -N 2 -N 3
  rpc.nfsd: writing fd to kernel failed: errno 111 (Connection refused)
  rpc.nfsd: unable to set any sockets for nfsd

Add a flag to svc_version to tell the rpc layer it can safely ignore an
rpcbind failure in the NFSv4-only case.

Reported-by: Gareth Williams <gareth@garethwilliams.me.uk>
Reviewed-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Kinglong Mee <kinglongmee@gmail.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
fs/nfsd/nfs4proc.c
include/linux/sunrpc/svc.h
net/sunrpc/svc.c

index 7bac4bd..41e34df 100644 (file)
@@ -1882,6 +1882,7 @@ struct svc_version        nfsd_version4 = {
                .vs_proc        = nfsd_procedures4,
                .vs_dispatch    = nfsd_dispatch,
                .vs_xdrsize     = NFS4_SVC_XDRSIZE,
+               .vs_rpcb_optnl  = 1,
 };
 
 /*
index b631642..04e7632 100644 (file)
@@ -386,8 +386,10 @@ struct svc_version {
        struct svc_procedure *  vs_proc;        /* per-procedure info */
        u32                     vs_xdrsize;     /* xdrsize needed for this version */
 
-       unsigned int            vs_hidden : 1;  /* Don't register with portmapper.
+       unsigned int            vs_hidden : 1,  /* Don't register with portmapper.
                                                 * Only used for nfsacl so far. */
+                               vs_rpcb_optnl:1;/* Don't care the result of register.
+                                                * Only used for nfsv4. */
 
        /* Override dispatch function (e.g. when caching replies).
         * A return value of 0 means drop the request. 
index e7fbe36..5de6801 100644 (file)
@@ -916,9 +916,6 @@ static int __svc_register(struct net *net, const char *progname,
 #endif
        }
 
-       if (error < 0)
-               printk(KERN_WARNING "svc: failed to register %sv%u RPC "
-                       "service (errno %d).\n", progname, version, -error);
        return error;
 }
 
@@ -937,6 +934,7 @@ int svc_register(const struct svc_serv *serv, struct net *net,
                 const unsigned short port)
 {
        struct svc_program      *progp;
+       struct svc_version      *vers;
        unsigned int            i;
        int                     error = 0;
 
@@ -946,7 +944,8 @@ int svc_register(const struct svc_serv *serv, struct net *net,
 
        for (progp = serv->sv_program; progp; progp = progp->pg_next) {
                for (i = 0; i < progp->pg_nvers; i++) {
-                       if (progp->pg_vers[i] == NULL)
+                       vers = progp->pg_vers[i];
+                       if (vers == NULL)
                                continue;
 
                        dprintk("svc: svc_register(%sv%d, %s, %u, %u)%s\n",
@@ -955,16 +954,26 @@ int svc_register(const struct svc_serv *serv, struct net *net,
                                        proto == IPPROTO_UDP?  "udp" : "tcp",
                                        port,
                                        family,
-                                       progp->pg_vers[i]->vs_hidden?
-                                               " (but not telling portmap)" : "");
+                                       vers->vs_hidden ?
+                                       " (but not telling portmap)" : "");
 
-                       if (progp->pg_vers[i]->vs_hidden)
+                       if (vers->vs_hidden)
                                continue;
 
                        error = __svc_register(net, progp->pg_name, progp->pg_prog,
                                                i, family, proto, port);
-                       if (error < 0)
+
+                       if (vers->vs_rpcb_optnl) {
+                               error = 0;
+                               continue;
+                       }
+
+                       if (error < 0) {
+                               printk(KERN_WARNING "svc: failed to register "
+                                       "%sv%u RPC service (errno %d).\n",
+                                       progp->pg_name, i, -error);
                                break;
+                       }
                }
        }