svc_register() assigns each pg_rpcbind_set() result to the same "error"
and returns the last one. The break only leaves the version loop, so any
program after a failed one overwrites its error.

Keep the first error instead of the last.

This is a flag day for CONFIG_NFS_LOCALIO=y, which converges on the
CONFIG_NFS_LOCALIO=n behaviour (the Kconfig default):

- NFSv4 is unaffected: nfsd_version4 sets vs_rpcb_optnl, so
  svc_generic_rpcbind_set() returns 0 for it however __svc_register() went.
- nfsd_version3 does not set it, and nfsd_net_init() enables every
  supported version, so a v3-enabled server with no reachable rpcbind now
  fails to bring up any listener. svc_bind() does not catch that earlier:
  rpcb_create_local() falls through to rpcb_create_local_net(), which
  passes RPC_CLNT_CREATE_NOPING and returns 0 with nothing listening.
- A partial failure (nfsd registered, nfsacl not) tears the listener down
  but leaves the nfsd entry in rpcbind until the next svc_rpcb_setup()
  clears it.

Fixes: 642ee6b209c2 ("SUNRPC: Allow further customisation of RPC program 
registration")
Signed-off-by: Jeff Layton <[email protected]>
Assisted-by: LLM
---
 net/sunrpc/svc.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index 8297bad2b177..4f402bbf97ba 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -1208,13 +1208,16 @@ int svc_register(const struct svc_serv *serv, struct 
net *net,
                struct svc_program *progp = &serv->sv_programs[p];
 
                for (i = 0; i < progp->pg_nvers; i++) {
+                       int ret;
 
-                       error = progp->pg_rpcbind_set(net, progp, i,
+                       ret = progp->pg_rpcbind_set(net, progp, i,
                                        family, proto, port);
-                       if (error < 0) {
+                       if (ret < 0) {
                                printk(KERN_WARNING "svc: failed to register "
                                        "%sv%u RPC service (errno %d).\n",
-                                       progp->pg_name, i, -error);
+                                       progp->pg_name, i, -ret);
+                               if (!error)
+                                       error = ret;
                                break;
                        }
                }

-- 
2.55.0


Reply via email to