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 <[email protected]>
---
 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


Reply via email to