svc_unregister() clears the rpcbind entry for every non-hidden program and version. svc_rpcb_setup() runs it to drop stale entries when a serv binds, and svc_rpcb_cleanup() runs it when one goes away. An nfsd serv with v3 and v4 enabled sweeps four or five entries, so a local rpcbind that never replies costs that many timeouts, twice per NFSD_CMD_LISTENER_SET, all under nfsd_mutex. Give up after the first call that gets no answer. Assisted-by: LLM Signed-off-by: Jeff Layton --- net/sunrpc/svc.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index e437e99a0b36..bccaeb8dfba8 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -1277,8 +1277,8 @@ int svc_register(struct svc_serv *serv, struct net *net, * any "inet6" entries anyway. So a PMAP_UNSET should be sufficient * in this case to clear all existing entries for [program, version]. */ -static void __svc_unregister(struct net *net, const u32 program, const u32 version, - const char *progname) +static int __svc_unregister(struct net *net, const u32 program, const u32 version, + const char *progname) { int error; @@ -1292,6 +1292,7 @@ static void __svc_unregister(struct net *net, const u32 program, const u32 versi error = rpcb_register(net, program, version, 0, 0); trace_svc_unregister(progname, version, error); + return error; } /* @@ -1318,10 +1319,13 @@ static void svc_unregister(const struct svc_serv *serv, struct net *net) continue; if (progp->pg_vers[i]->vs_hidden) continue; - __svc_unregister(net, progp->pg_prog, i, progp->pg_name); + if (__svc_unregister(net, progp->pg_prog, i, + progp->pg_name) == -ENAVAIL) + goto out; } } +out: rcu_read_lock(); sighand = rcu_dereference(current->sighand); spin_lock_irqsave(&sighand->siglock, flags); -- 2.55.0