]> www.infradead.org Git - users/hch/misc.git/commitdiff
nfsd: unregister with rpcbind when deleting a transport
authorOlga Kornievskaia <okorniev@redhat.com>
Tue, 19 Aug 2025 18:04:02 +0000 (14:04 -0400)
committerChuck Lever <chuck.lever@oracle.com>
Sun, 21 Sep 2025 23:24:50 +0000 (19:24 -0400)
When a listener is added, a part of creation of transport also registers
program/port with rpcbind. However, when the listener is removed,
while transport goes away, rpcbind still has the entry for that
port/type.

When deleting the transport, unregister with rpcbind when appropriate.

---v2 created a new xpt_flag XPT_RPCB_UNREG to mark TCP and UDP
transport and at xprt destroy send rpcbind unregister if flag set.

Suggested-by: Chuck Lever <chuck.lever@oracle.com>
Fixes: d093c9089260 ("nfsd: fix management of listener transports")
Cc: stable@vger.kernel.org
Signed-off-by: Olga Kornievskaia <okorniev@redhat.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
include/linux/sunrpc/svc_xprt.h
net/sunrpc/svc_xprt.c
net/sunrpc/svcsock.c

index 369a89aea18618748607ee943247c327bf62c8d5..2b886f7eb29562c195017c47bdd853776068a351 100644 (file)
@@ -104,6 +104,9 @@ enum {
                                 * it has access to.  It is NOT counted
                                 * in ->sv_tmpcnt.
                                 */
+       XPT_RPCB_UNREG,         /* transport that needs unregistering
+                                * with rpcbind (TCP, UDP) on destroy
+                                */
 };
 
 /*
index 8b1837228799c5e3ad052cfa831ff52ba12de6e1..b800d704d8076927764f6f8483831de2f9c250df 100644 (file)
@@ -1014,6 +1014,19 @@ static void svc_delete_xprt(struct svc_xprt *xprt)
        struct svc_serv *serv = xprt->xpt_server;
        struct svc_deferred_req *dr;
 
+       /* unregister with rpcbind for when transport type is TCP or UDP.
+        */
+       if (test_bit(XPT_RPCB_UNREG, &xprt->xpt_flags)) {
+               struct svc_sock *svsk = container_of(xprt, struct svc_sock,
+                                                    sk_xprt);
+               struct socket *sock = svsk->sk_sock;
+
+               if (svc_register(serv, xprt->xpt_net, sock->sk->sk_family,
+                                sock->sk->sk_protocol, 0) < 0)
+                       pr_warn("failed to unregister %s with rpcbind\n",
+                               xprt->xpt_class->xcl_name);
+       }
+
        if (test_and_set_bit(XPT_DEAD, &xprt->xpt_flags))
                return;
 
index c0d5a27ba674b05f76a506f147a9594f1f6b7936..7b90abc5cf0ee1520796b2f38fcb977417009830 100644 (file)
@@ -836,6 +836,7 @@ static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv)
        /* data might have come in before data_ready set up */
        set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
        set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags);
+       set_bit(XPT_RPCB_UNREG, &svsk->sk_xprt.xpt_flags);
 
        /* make sure we get destination address info */
        switch (svsk->sk_sk->sk_family) {
@@ -1350,6 +1351,7 @@ static void svc_tcp_init(struct svc_sock *svsk, struct svc_serv *serv)
        if (sk->sk_state == TCP_LISTEN) {
                strcpy(svsk->sk_xprt.xpt_remotebuf, "listener");
                set_bit(XPT_LISTENER, &svsk->sk_xprt.xpt_flags);
+               set_bit(XPT_RPCB_UNREG, &svsk->sk_xprt.xpt_flags);
                sk->sk_data_ready = svc_tcp_listen_data_ready;
                set_bit(XPT_CONN, &svsk->sk_xprt.xpt_flags);
        } else {