Re: [PATCH v2 4/8] SUNRPC: undo partial rpcbind registrations when svc_register() fails

"Chuck Lever" <[email protected]>
Newsgroups gmane.linux.nfs,gmane.linux.kernel,gmane.linux.network
Message-ID <[email protected]>

On Tue, Aug 11, 2026, at 8:03 AM, Jeff Layton wrote:
> svc_register() registers each [program, version] in turn. On failure the
> caller tears the listener down -- svc_setup_socket() frees the svc_sock and
> svc_create_socket() releases the socket -- but the entries that were already
> set stay in rpcbind, now pointing at a closed port. XPT_RPCB_UNREG is set
> later, in svc_udp_init()/svc_tcp_init(), so svc_delete_xprt() never runs for
> this transport and nothing clears them.
>
> Unwind on failure, and stop the walk there rather than registering the
> programs after it. rpcbind matches RPCBPROC_UNSET on
> [program, version, netid] and ignores the address, so the unwind clears the
> netid, not just the port -- the same granularity svc_delete_xprt() already
> unregisters at.
>
> Assisted-by: LLM
> Signed-off-by: Jeff Layton <[email protected]>
> ---
>  net/sunrpc/svc.c | 31 ++++++++++++++++++++++++++++++-
>  1 file changed, 30 insertions(+), 1 deletion(-)
>
> diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
> index 4f402bbf97ba..9ffa87007004 100644
> --- a/net/sunrpc/svc.c
> +++ b/net/sunrpc/svc.c
> @@ -1183,6 +1183,29 @@ int svc_generic_rpcbind_set(struct net *net,
>  }
>  EXPORT_SYMBOL_GPL(svc_generic_rpcbind_set);
> 
> +/*
> + * Undo the [program, version] registrations that this svc_register() 
> call
> + * already made, stopping at version @nvers of program @nprog.
> + *
> + * Note that rpcbind matches RPCBPROC_UNSET on [program, version, 
> netid] and
> + * ignores the address, so this clears the netid rather than the one 
> port.
> + * That is the granularity svc_delete_xprt() unregisters at as well.
> + */
> +static void svc_unwind_register(const struct svc_serv *serv, struct 
> net *net,
> +				const int family, const unsigned short proto,
> +				unsigned int nprog, unsigned int nvers)
> +{
> +	unsigned int p, i;
> +
> +	for (p = 0; p <= nprog; p++) {
> +		struct svc_program *progp = &serv->sv_programs[p];
> +		unsigned int last = p < nprog ? progp->pg_nvers : nvers;
> +
> +		for (i = 0; i < last; i++)
> +			progp->pg_rpcbind_set(net, progp, i, family, proto, 0);
> +	}
> +}

For an IPv4 listener, the port-zero callback falls back through
__svc_rpcb_register4() to rpcb_register(). PMAPPROC_UNSET ignores
its protocol argument, so unwinding a partially successful TCP
registration also removes the mappings for existing listeners on
other transports, I would think.

It might be that the best the kernel can do here is tear everything
down if one registration fails.


-- 
Chuck Lever
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.