From nobody Fri Sep 25 16:03:02 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2130F56C658; Thu, 10 Sep 2026 18:00:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789063254; cv=none; b=qPlvNzQIHDv0SlV5UxRty9gptD1YNntHKU5Fl9I22gIrCkeCrTQoEoepn41FaqRjf/OeQo1AVfY5fIqaCreSU7CMv1aENqvgdtFol5a5QAI8Uun6CEFTQfe3LHabNf0+kMUQPCIxohAGcaQILyVm0Ewo5pJXwytqgkvKqdPfEfA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789063254; c=relaxed/simple; bh=Y52NZDtdhSFudORqf/hrNCBln5i18PiOFw7JX8yMWhQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=E4RXTZIdHJ5/RvsO3cic2lTS/smyjiTTgUhUlXEKRMbQb9g2qYk4uLVqsG2Fxgl9GwJIp5VCFskucjoixtneR5Y5+64L+YtDF8uynp+tYCBzrLmhLzCCD7jr8IVvOZ/8+FZ8DfPZN8/TxdaSgrlAJmBkFydkR37MgN96ntGWqjE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RULGDe/j; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="RULGDe/j" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2E7711F00893; Thu, 10 Sep 2026 18:00:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1789063252; bh=tOMolZ+poJSqSTHyLfPS1I8lq1rbD6wxR9LijPFNbic=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=RULGDe/jeqRO4l4Goi/S0tYrD2LS7q4yq5w47N956abhoWzxkMuFMkuZUScfMf3u8 QfSQwCpRWbGmcIR1UJyRS7GXjMKELqsjLtljdPNkXVboLEk16hMpEXMX2cq6Wn7PtT HsVisdXZdVPujdiwX67j2vKfKK/USH8kmeUzw27YTNereUFUOng6/oGrXsGON81Q8z 5U+Yafw2++DOpYD2XVvIFywN0Ygszfk6gQC6yEJO5NImrrduBLu5AMWQsIK/2s1gnr bRzz1NjxKjQAE+N+Z0YkIykwq0FiRavWHNYAXjxTeKQoRokuDgjvhtpUB/VDWJf1Kt FjAc3QEy9fztQ== From: Jeff Layton Date: Thu, 10 Sep 2026 14:00:34 -0400 Subject: [PATCH 1/5] SUNRPC: allow a service to opt out of rpcbind registration Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260910-nfsd-norpcb-v1-1-b4d5182d634c@kernel.org> References: <20260910-nfsd-norpcb-v1-0-b4d5182d634c@kernel.org> In-Reply-To: <20260910-nfsd-norpcb-v1-0-b4d5182d634c@kernel.org> To: Trond Myklebust , Anna Schumaker , Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Donald Hunter , Shuah Khan Cc: linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, linux-kselftest@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=2210; i=jlayton@kernel.org; h=from:subject:message-id; bh=Y52NZDtdhSFudORqf/hrNCBln5i18PiOFw7JX8yMWhQ=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBqovBP0GMqGThnFqt7S2XqJSKkBnWEKyjIBpTip NCwhJb2pR6JAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaqLwTwAKCRAADmhBGVaC FV23D/9TQItB3ljakBGNtbp6C0PcGLUdldMeqWNiKMEz+E7fyKlleELqjhJc7YRdFOQ2yDxbu4C H6XbKHMXB5tsy9dlmYf+ytCR4MKlMkmjwaWG8qXDyn9AgoQH0JTiXe2HlfaKqJa3e3rql5Sq4ni YRaw5UMsdEdWuLEMpDwN9DaYp2bTzb4MHorkE7pdWqqzCADYrNqzQz8PMISW4W3R86ZZSdFv/sN qOX4BfyBbR2AeOxVe6/zA/GiUhU/V0zWR021ZWhPwUqHk6iroz6U1Zm51oaBNisILYGcI25nbKz qXb9/rP8EH6B/5Z9ZqccDOz2NzKNg0poN1bpg5myOQLAwXAacC6/CeFi6R21YNeTjtOJDi0f/em bUh//7zXrMOMt8NHMfily1Jd+JtCPws3hqWGVsB+mhyQnr5PzbsVleikFxpf/fP0mHl+Y4/88Au o1UZp5f5skpBEHkI4oZQ4mNASZyrQSG58weiwGPO+zE8/UBEgz5glMxMohBBd0FlV00boCGH8RH Q/WDFoaH6J2ACFMAdPMj7kjbNHXDlnMv6xqhF8pevYhVxfGZ19YTi/Bcs3x8uwr9O1IpGLfogrR sMwz6s5Mh8Ex5gO9Qz4vPlUrdCbcRcnY1YRjE+1vGsw0cGulNrKd0qtBrMr71T1c52tzYWLa1cC 3n0HMYZ3QfFlnyA== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 svc_bind() creates the local rpcbind client, and svc_register() then makes one synchronous call for each program and version. Both run under the caller's mutex. A caller that registers from userland needs neither. Add sv_no_rpcbind to struct svc_serv, and fix up the code to honor it. No caller sets the flag yet, so behaviour does not change. Assisted-by: LLM Signed-off-by: Jeff Layton --- include/linux/sunrpc/svc.h | 2 ++ net/sunrpc/svc.c | 5 +++++ net/sunrpc/svc_xprt.c | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index 5fa9417e034d..7f09db6a360c 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -87,6 +87,8 @@ struct svc_serv { char * sv_name; /* service name */ =20 bool sv_is_pooled; /* is this a pooled service? */ + /* Caller registers with rpcbind itself. Set before svc_bind(). */ + bool sv_no_rpcbind; struct svc_pool * sv_pools; /* array of thread pools */ int (*sv_threadfn)(void *data); =20 diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index f73412e123a1..7e23af94a719 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -337,6 +337,8 @@ static int svc_uses_rpcbind(struct svc_serv *serv) =20 int svc_bind(struct svc_serv *serv, struct net *net) { + if (serv->sv_no_rpcbind) + return 0; if (!svc_uses_rpcbind(serv)) return 0; return svc_rpcb_setup(serv, net); @@ -1235,6 +1237,9 @@ int svc_register(struct svc_serv *serv, struct net *n= et, if (proto =3D=3D 0 && port =3D=3D 0) return -EINVAL; =20 + if (serv->sv_no_rpcbind) + return 0; + for (p =3D 0; p < serv->sv_nprogs; p++) { struct svc_program *progp =3D &serv->sv_programs[p]; =20 diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index d5634dd6d6cc..1a2c87e4d951 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c @@ -1266,7 +1266,7 @@ void svc_xprt_destroy_all(struct svc_serv *serv, stru= ct net *net, msleep(delay++); } =20 - if (unregister) + if (unregister && !serv->sv_no_rpcbind) svc_rpcb_cleanup(serv, net); } EXPORT_SYMBOL_GPL(svc_xprt_destroy_all); --=20 2.55.0 From nobody Fri Sep 25 16:03:02 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A33B9577E41; Thu, 10 Sep 2026 18:00:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789063256; cv=none; b=X9IykVJ09MbQh2BCKCXj3WS2OjQSqyxnLm0VTOOVuXsVmhDOT1cNtB7P531e9LQ7CvWbmNNMNVLcUEJV8aiRRyRNba7BHh6Z5PhjHg8h8LIX4BmJyAmTJvAZB3xtxIwpzzxBVBSP86e5q5JdbTV7+9mE80kKAQt0r9qYxC+EQBw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789063256; c=relaxed/simple; bh=dYm5b7B6dTvNKjVYzuF7/FkF8IDWphASM2cJV/5trG4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=kWBtCKn1Q87rT4ymdW+KEr7yCn679+DdWWOOG1N1ZAFDgEvUjJU6VT5efUUDn5o2EOIYFAHLfEecP9wOTdg+m+CI6J4WY9FOlyl94nJHqf4sbMolCYozBemiFBCgJJN7kY/MpS3jwmKRQrurQ+JVD5dYzMqOnh3WUDmhHHokd1M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Q/morVwf; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Q/morVwf" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C3D871F0089A; Thu, 10 Sep 2026 18:00:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1789063254; bh=QH3G09fgNYNq57/vr1pk3tneJpQFCpXfha0cp9uQYVE=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=Q/morVwfPM5FKSX/dcLsyMDO/e12v9+T3J11hCysgzSLB589D7QZ10gxtmqrJAG/b 5K9k6xR/j4Mw0dcZSFmC6Kq2KelfydKltrrn5OcX0IxuWI5wSG4nElHEedzk9/rngb YgFMexodG/DrDdkxXCsy9QeDF60/0/+dO6QEcM0kpGlg7l1YkIdp5xij8Q6PW85vGW GVfLioSMGgALzzreDpMgnAQy2ykZSMSc5Sv1ptWEwbBHKOZ15SNm2UVFRUIx7A+tYU yOKMtFn8eaJ0YjsNpUsmyoWJ8RO0PLdiyOAvE7UVrwhpSgTS4vWp4ltJTzr4S+ZXnA trIi0Omfkv5OA== From: Jeff Layton Date: Thu, 10 Sep 2026 14:00:35 -0400 Subject: [PATCH 2/5] NFSD: add a userspace-rpcbind flag to listener_set Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260910-nfsd-norpcb-v1-2-b4d5182d634c@kernel.org> References: <20260910-nfsd-norpcb-v1-0-b4d5182d634c@kernel.org> In-Reply-To: <20260910-nfsd-norpcb-v1-0-b4d5182d634c@kernel.org> To: Trond Myklebust , Anna Schumaker , Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Donald Hunter , Shuah Khan Cc: linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, linux-kselftest@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=5624; i=jlayton@kernel.org; h=from:subject:message-id; bh=dYm5b7B6dTvNKjVYzuF7/FkF8IDWphASM2cJV/5trG4=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBqovBPj/3xfeqAtK2malIwl/EFi7tMqrHBdBUsM bigld4kDDyJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaqLwTwAKCRAADmhBGVaC FbQxEACA+tPV6VAkVXrCrfqK3o0ASvd4vQyEHinNptRbc0OwwnCXDvHmqknhGH8QztPkxp83SQT A/+GOmCXq4Od+FFeKQ6qL9/gZqPA7bejsSt89cGKVNoOgit5Z9gx5al782YO/WEkADBiWBEreL/ RtFOUIzJTi6roDPfMCyAazQtk5jjNWOhbZ/o5QcJaKOXds2s1hb6PhxQOgQibc3Ipzqtv+mrdZF Aqx1RLHVjreHRkjKqKbUbeuTjTvgFM+STJV8YueLk7acDvnva8BsF057mCHnkrRF4cDtfQjovDV D0gOtQQWS1mZt9lnQTzfoVnRGQ+KFawO7nPa5v1/Cj62/8k3rhuM5X4OhPLory/aUPVa/ITqIro PlOJZu+jZpH208fajwWy9XANgBqRZuI+svHbruDnH4TfRoc80o1kYhxPyFQnZVaU2AX1fV/2MYW yAf3ajkXiahCVxHKKAg8mnrkjVRPpLZ4E2Nwo98buZmwoQkmQucB7T7OYcdC7+YBjyPEcvska06 +AWxUcQJnHkxdZ6wmY8eDZ/2aBXNl0fbO9Sq8d7lB6SG3usk9MRNWNYJ7cR8YErOFSqfJ0yzn8Q kkSo3wo4t1AnV46v1+7Y6tOzbT7Fnv76oC9zARssmTu9LgoI3QJ/zONT2/IOrUKJAZiyTxsc5pD KkoLAwyk6fZuIkw== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 Describe the interface that lets a caller take over rpcbind registration. The request gains a userspace-rpcbind flag. The reply echoes the flag, lists the programs and versions that the caller should register, and names the listeners that came up. NLM is absent. lockd owns its own svc_serv and still registers itself. Assisted-by: LLM Signed-off-by: Jeff Layton --- Documentation/netlink/specs/nfsd.yaml | 55 +++++++++++++++++++++++++++++++= +++- fs/nfsd/netlink.c | 5 ++-- include/uapi/linux/nfsd_netlink.h | 20 +++++++++++++ 3 files changed, 77 insertions(+), 3 deletions(-) diff --git a/Documentation/netlink/specs/nfsd.yaml b/Documentation/netlink/= specs/nfsd.yaml index 642268819c6f..9ae37bf3ea71 100644 --- a/Documentation/netlink/specs/nfsd.yaml +++ b/Documentation/netlink/specs/nfsd.yaml @@ -42,6 +42,15 @@ definitions: - none - tls - mtls + - + type: flags + name: rpcbind-flags + doc: >- + Constraints that apply to an rpcbind registration. no-udp means the + kernel would not have registered this program and version over UDP, + so the caller must skip the udp and udp6 netids for it. + entries: + - no-udp =20 attribute-sets: - @@ -159,6 +168,23 @@ attribute-sets: - name: transport-name type: string + - + name: rpcbind + attributes: + - + name: program + type: u32 + doc: RPC program number to register. + - + name: version + type: u32 + doc: RPC version number to register. + - + name: flags + type: u32 + enum: rpcbind-flags + enum-as-flags: true + doc: Constraints on the listeners this entry applies to. - name: server-sock attributes: @@ -167,6 +193,24 @@ attribute-sets: type: nest nested-attributes: sock multi-attr: true + - + name: userspace-rpcbind + type: flag + doc: >- + The caller registers the listeners with rpcbind itself, so the + kernel must not do it. The kernel echoes this attribute in the + reply when it accepts the request. Ownership cannot change while + a server exists. + - + name: rpcbind + type: nest + nested-attributes: rpcbind + multi-attr: true + doc: >- + A program and version that the caller should register for every + listener reported in the same reply, except the netids that flags + rules out. Reply only. NLM is absent because lockd still + registers itself. - name: pool-mode attributes: @@ -483,13 +527,22 @@ operations: - version - name: listener-set - doc: set nfs running sockets + doc: >- + set nfs running sockets. A request that carries userspace-rpcbind + is answered with a reply rather than a bare ack, and the addr list + in that reply names only the listeners that have an rpcbind netid. attribute-set: server-sock flags: [admin-perm] do: request: attributes: - addr + - userspace-rpcbind + reply: + attributes: + - addr + - userspace-rpcbind + - rpcbind - name: listener-get doc: get nfs running listeners diff --git a/fs/nfsd/netlink.c b/fs/nfsd/netlink.c index eba8b353f412..88a4a4ffcb7f 100644 --- a/fs/nfsd/netlink.c +++ b/fs/nfsd/netlink.c @@ -79,8 +79,9 @@ static const struct nla_policy nfsd_version_set_nl_policy= [NFSD_A_SERVER_PROTO_VE }; =20 /* NFSD_CMD_LISTENER_SET - do */ -static const struct nla_policy nfsd_listener_set_nl_policy[NFSD_A_SERVER_S= OCK_ADDR + 1] =3D { +static const struct nla_policy nfsd_listener_set_nl_policy[NFSD_A_SERVER_S= OCK_USERSPACE_RPCBIND + 1] =3D { [NFSD_A_SERVER_SOCK_ADDR] =3D NLA_POLICY_NESTED(nfsd_sock_nl_policy), + [NFSD_A_SERVER_SOCK_USERSPACE_RPCBIND] =3D { .type =3D NLA_FLAG, }, }; =20 /* NFSD_CMD_POOL_MODE_SET - do */ @@ -153,7 +154,7 @@ static const struct genl_split_ops nfsd_nl_ops[] =3D { .cmd =3D NFSD_CMD_LISTENER_SET, .doit =3D nfsd_nl_listener_set_doit, .policy =3D nfsd_listener_set_nl_policy, - .maxattr =3D NFSD_A_SERVER_SOCK_ADDR, + .maxattr =3D NFSD_A_SERVER_SOCK_USERSPACE_RPCBIND, .flags =3D GENL_ADMIN_PERM | GENL_CMD_CAP_DO, }, { diff --git a/include/uapi/linux/nfsd_netlink.h b/include/uapi/linux/nfsd_ne= tlink.h index 87da1d0bb21e..c125af0cc6a5 100644 --- a/include/uapi/linux/nfsd_netlink.h +++ b/include/uapi/linux/nfsd_netlink.h @@ -50,6 +50,15 @@ enum nfsd_xprtsec_mode { NFSD_XPRTSEC_MODE_MTLS =3D 4, }; =20 +/* + * Constraints that apply to an rpcbind registration. no-udp means the ker= nel + * would not have registered this program and version over UDP, so the cal= ler + * must skip the udp and udp6 netids for it. + */ +enum nfsd_rpcbind_flags { + NFSD_RPCBIND_FLAGS_NO_UDP =3D 1, +}; + enum { NFSD_A_CACHE_NOTIFY_CACHE_TYPE =3D 1, =20 @@ -113,8 +122,19 @@ enum { NFSD_A_SOCK_MAX =3D (__NFSD_A_SOCK_MAX - 1) }; =20 +enum { + NFSD_A_RPCBIND_PROGRAM =3D 1, + NFSD_A_RPCBIND_VERSION, + NFSD_A_RPCBIND_FLAGS, + + __NFSD_A_RPCBIND_MAX, + NFSD_A_RPCBIND_MAX =3D (__NFSD_A_RPCBIND_MAX - 1) +}; + enum { NFSD_A_SERVER_SOCK_ADDR =3D 1, + NFSD_A_SERVER_SOCK_USERSPACE_RPCBIND, + NFSD_A_SERVER_SOCK_RPCBIND, =20 __NFSD_A_SERVER_SOCK_MAX, NFSD_A_SERVER_SOCK_MAX =3D (__NFSD_A_SERVER_SOCK_MAX - 1) --=20 2.55.0 From nobody Fri Sep 25 16:03:02 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2C31957D232; Thu, 10 Sep 2026 18:00:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789063257; cv=none; b=R4Xuv2a4hFgqpR86sGeRZPCX2X7pbaTP7PEiTgXcS7BaheKGnAkVa5iWsTCZ5I5xbJLwOkiWOFz2TvwSTQekaXdP2Dm3eh8LO48v2ZlUHPrEcS87ZwJp5/+tg1GEackk5B/TG9aIh7K2JgtJ8Xm2blAHtX+x/PYYdhT1CF/7a5o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789063257; c=relaxed/simple; bh=zENH7b8VS6SakqPNlRmEcRWCMYqbT1hHXJdGm8gMVvg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=pUq0xry94COX3yycIUDKot5/68GfYPa1ip8mQuLQXaUcG5PIstM0jUtcZEgRrsrql481pG6R2EBMR8iBK5kWHqnaJaB8/NbZgFvvhVpjLnrlOXdhszbBUzWYXPStopi5B4/c26tsGFxWwoiy9GfERA0kUNx9GVBopAOljqztc3s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Xrv+tH1o; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Xrv+tH1o" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 642191F00898; Thu, 10 Sep 2026 18:00:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1789063255; bh=ujhKR+xAMJLiLYz8s7j2Mat0/rmlxI7pd5yNuRJQ3mI=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=Xrv+tH1ovf4kwa8B5yDtkQ6agxgpjjxr2bJjhlVZCssfuQC3LkT/El5jcZufIU73D ku83B6BLPKMALObQL8r2kru+p81auH4BNy+cIkz5OleCPwwZc140X530ONaCan2AMj C6hEwhwyTVjt/EoKLdykmLofOkDWfiFzqRnHY/2uzgVxrYKOz+b8NS4f/MGl3wqtQR u7G14+/MKWzFXtN/1k4eh/CIT4OJJgV7gZEhJxf+x8Dv7zXrivI8u7P0TE05SW4oA3 qT6aiClWcH1rOCbT83RLvKxocpVxDaMSdhNcQzQkcFrW1zILbz+3mqnD8BHI4EUDAC fAFgxUThltHug== From: Jeff Layton Date: Thu, 10 Sep 2026 14:00:36 -0400 Subject: [PATCH 3/5] NFSD: honour the userspace-rpcbind flag in listener_set Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260910-nfsd-norpcb-v1-3-b4d5182d634c@kernel.org> References: <20260910-nfsd-norpcb-v1-0-b4d5182d634c@kernel.org> In-Reply-To: <20260910-nfsd-norpcb-v1-0-b4d5182d634c@kernel.org> To: Trond Myklebust , Anna Schumaker , Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Donald Hunter , Shuah Khan Cc: linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, linux-kselftest@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=4666; i=jlayton@kernel.org; h=from:subject:message-id; bh=zENH7b8VS6SakqPNlRmEcRWCMYqbT1hHXJdGm8gMVvg=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBqovBQpwoDrkXCPlrKRvUYIzPISrhEl6o6MjYsy nfa5iLm8MaJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaqLwUAAKCRAADmhBGVaC FetnD/9o1JIGDt4c+BF9EzEeCA6bp2t+7ZSX/LK3ELENJZ6jd6jaEss3hLT8eWklPYoLtgxDyrM OWvN7UDUmyELJuv6UTdvmyTv62yhTwW+2VgSUlxUvOV8rRxLUlaDiizr1ti832U3izLayJ6xQqE e4irESrcXkHhR3zHwNg+2YND8lVo1W42cXN2JiUlgMwmRhGQF3UROxnKNEnztAqoL80wEnK595s ysUSFTQuNp4qUPb2uYAs8zVHlfNQMCS+7rIN6chCeu49IEqtV0O5wCWkl8ovbU1cV+lSRKhQvYV 6OlLNNL9mxzvePWSXuFD6+XXc1NN+YFd0AlfUFGCLEQ3Sbhma9D2cJboyVM85RL6iFg86CG8gOZ 7ODiTRZMUPhgbT9OmQN2nX3yT4jQUtBNKfOiB/haB9gZtlv5Uz4HfqzSiTW733LKETc761GeR2H jg8etPc3qkFFuiKTyzx9D4x8kDfvU2idE3Jby8gm+EU1G7aWAA236LB7MmgTR3nxek236XOs2CQ a8qSrNhDBdXTmt1ZfA0P+6R6GC4COpL/QoJsO24Jt9WYf2n+UG4q9jDwGB8NkVOSePUKL/zfweG 4TJLxnZ+/MyJq7ZvsgyfV4RhgqYBzAmtma9HQgvBplntEEALET58dgrtUtlAbMTaKuXIUmO68QK 74e1lr8pSFBuIUw== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 A listener_set request that carries userspace-rpcbind now sets sv_no_rpcbind on the serv. The kernel then makes no rpcbind call at all, avoiding synchronous rpcbind RPCs under nfsd_mutex. lockd is unaffected. It owns a separate svc_serv and still registers NLM. Assisted-by: LLM Signed-off-by: Jeff Layton --- fs/nfsd/nfsctl.c | 23 +++++++++++++++++------ fs/nfsd/nfsd.h | 2 +- fs/nfsd/nfssvc.c | 14 ++++++++++++-- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 1be8f98a293d..63746334a46f 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -748,7 +748,7 @@ static ssize_t __write_ports_addfd(char *buf, struct ne= t *net, const struct cred return -EINVAL; trace_nfsd_ctl_ports_addfd(net, fd); =20 - err =3D nfsd_create_serv(net); + err =3D nfsd_create_serv(net, false); if (err !=3D 0) return err; =20 @@ -780,7 +780,7 @@ static ssize_t __write_ports_addxprt(char *buf, struct = net *net, const struct cr return -EINVAL; trace_nfsd_ctl_ports_addxprt(net, transport, port); =20 - err =3D nfsd_create_serv(net); + err =3D nfsd_create_serv(net, false); if (err !=3D 0) return err; =20 @@ -2095,6 +2095,7 @@ int nfsd_nl_listener_set_doit(struct sk_buff *skb, st= ruct genl_info *info) unsigned int rpcb_failures; const struct nlattr *attr; bool skipped_rpcb =3D false; + bool userspace_rpcbind; bool bad_rpcb =3D false; struct svc_serv *serv; LIST_HEAD(permsocks); @@ -2111,15 +2112,25 @@ int nfsd_nl_listener_set_doit(struct sk_buff *skb, = struct genl_info *info) if (err) return err; =20 + userspace_rpcbind =3D nla_get_flag(info->attrs[NFSD_A_SERVER_SOCK_USERSPA= CE_RPCBIND]); + mutex_lock(&nfsd_mutex); =20 - err =3D nfsd_create_serv(net); + nn =3D net_generic(net, nfsd_net_id); + + if (nn->nfsd_serv && nn->nfsd_serv->sv_no_rpcbind !=3D userspace_rpcbind)= { + NL_SET_ERR_MSG(info->extack, + "cannot change rpcbind ownership while a server exists"); + mutex_unlock(&nfsd_mutex); + return -EBUSY; + } + + err =3D nfsd_create_serv(net, userspace_rpcbind); if (err) { mutex_unlock(&nfsd_mutex); return err; } =20 - nn =3D net_generic(net, nfsd_net_id); serv =3D nn->nfsd_serv; =20 spin_lock_bh(&serv->sv_lock); @@ -2213,12 +2224,12 @@ int nfsd_nl_listener_set_doit(struct sk_buff *skb, = struct genl_info *info) continue; } =20 - flags =3D skipped_rpcb ? SVC_SOCK_ANONYMOUS : 0; + flags =3D (userspace_rpcbind || skipped_rpcb) ? SVC_SOCK_ANONYMOUS : 0; ret =3D svc_xprt_create_from_sa(serv, xcl_name, net, sa, flags, current_cred()); =20 hit_rpcb =3D false; - if (!skipped_rpcb && + if (!userspace_rpcbind && !skipped_rpcb && svc_rpcb_failure_count(serv) !=3D rpcb_failures) { skipped_rpcb =3D true; hit_rpcb =3D true; diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h index a145294c59c8..dcce45d58322 100644 --- a/fs/nfsd/nfsd.h +++ b/fs/nfsd/nfsd.h @@ -119,7 +119,7 @@ enum vers_op {NFSD_SET, NFSD_CLEAR, NFSD_TEST, NFSD_AVA= IL }; int nfsd_vers(struct nfsd_net *nn, int vers, enum vers_op change); int nfsd_minorversion(struct nfsd_net *nn, u32 minorversion, enum vers_op = change); void nfsd_reset_versions(struct nfsd_net *nn); -int nfsd_create_serv(struct net *net); +int nfsd_create_serv(struct net *net, bool no_rpcbind); void nfsd_destroy_serv(struct net *net); =20 #ifdef CONFIG_DEBUG_FS diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index c04ef9d180ce..ef520d0562d6 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -607,7 +607,14 @@ struct svc_rqst *nfsd_current_rqst(void) return NULL; } =20 -int nfsd_create_serv(struct net *net) +/** + * nfsd_create_serv - create the svc_serv for a namespace if it has none + * @net: network namespace to operate within + * @no_rpcbind: true if the caller registers the listeners with rpcbind + * + * Return: 0 on success or a negative errno. + */ +int nfsd_create_serv(struct net *net, bool no_rpcbind) { int error; struct nfsd_net *nn =3D net_generic(net, nfsd_net_id); @@ -635,6 +642,9 @@ int nfsd_create_serv(struct net *net) return -ENOMEM; } =20 + /* svc_bind() reads this, so set it first. */ + serv->sv_no_rpcbind =3D no_rpcbind; + error =3D svc_bind(serv, net); if (error < 0) { svc_destroy(&serv); @@ -775,7 +785,7 @@ nfsd_svc(int n, int *nthreads, struct net *net, const s= truct cred *cred, const c strscpy(nn->nfsd_name, scope ? scope : utsname()->nodename, sizeof(nn->nfsd_name)); =20 - error =3D nfsd_create_serv(net); + error =3D nfsd_create_serv(net, false); if (error) goto out; serv =3D nn->nfsd_serv; --=20 2.55.0 From nobody Fri Sep 25 16:03:02 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B8DC1569F0D; Thu, 10 Sep 2026 18:00:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789063259; cv=none; b=B19OzvEsqbcJxtQHa+o+JxJU2TFHR6AdChcAdngrcrXYGjnrFMhctQHm8AxQoz9c6C5d+MOsPEAXW3fX1/Tf428cxIQgfxB7k8waDX4OwoREIGTWrWQ0c2j+4wCHUBk/1SDS/5/xSm2Ma9dTtdqZ4D/qKogAk2kBJI1emus5hWc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789063259; c=relaxed/simple; bh=+5iFsTemV8PqtZ70nQIRFiTg3+tvwp5Sgi/gi++uO8g=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ZvOCY0CeEwCjMNsmWH+pa7+kpCE+ett4eTzUC+uR6/Fh7fdyvzo6fGmxYr65/lSpcx75VrVGrPNK1K2IiK4uEVx5dxp/PBZqZpnTp+I8d2Crd7XtmrcLt2C66iQuC25l26oTzF7Ucf7K8zjknoDERMbX8fFAXRGngHq+NzSMHe4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=DjN0hOS0; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="DjN0hOS0" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 045001F000FF; Thu, 10 Sep 2026 18:00:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1789063257; bh=wj2HVPTbhD4XSukugvxiG82e0lkkTSYyWfoYmuhwwXY=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=DjN0hOS0GxKH1nGt6Gl2Qe4kZrVVVUI4c4n7o2wmRIzFWTWW7UAh5Gu4DALK9BG28 IMKgbnYQ21nH7i3UwuIovcLC6IIHZ6B8g6NM9tef+f8VR34EAK6+SEMHc1wvVOZ3eG rjTB6LTipGumQ+DGdBBOrAp2/qxafQ0wAVCyOr0Eg86XbnfOcITPOCEaRWvAHv9cCT 1opjKHVmG9znQ7049MKMaCekW5k8am+sufgl2eOg+PaTpyTGhDf+IbmN/qpQacDMve 6DOQHhVyXvVK82+ULSYgNF3PZh8PH7jpi+/lIf5a9MkXrfWxywKlbCTOXD04NChFAa qJjUOotn3ngoQ== From: Jeff Layton Date: Thu, 10 Sep 2026 14:00:37 -0400 Subject: [PATCH 4/5] NFSD: report registerable programs in the listener_set reply Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260910-nfsd-norpcb-v1-4-b4d5182d634c@kernel.org> References: <20260910-nfsd-norpcb-v1-0-b4d5182d634c@kernel.org> In-Reply-To: <20260910-nfsd-norpcb-v1-0-b4d5182d634c@kernel.org> To: Trond Myklebust , Anna Schumaker , Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Donald Hunter , Shuah Khan Cc: linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, linux-kselftest@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=9145; i=jlayton@kernel.org; h=from:subject:message-id; bh=+5iFsTemV8PqtZ70nQIRFiTg3+tvwp5Sgi/gi++uO8g=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBqovBQpbS2Ij8DQ9X//7oQcxZwzgp8cWgxhFN5e sU1M87H44SJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaqLwUAAKCRAADmhBGVaC FXMZEACgSEFbc/arNz+5Cw0vg9Ll3Iq8rXJM3Bibyu3Qc+gjRhdNTfdp6rZG/WDCAqBiYjTJIgl Ox2VkmduWP6QPqY3yFYUptBoiYKxLnvXku/4YR4KzPm2+6YyQ2b+bOewiTvyFQ5y7Pbi+RwkfsR vU6B2l9dU7v5cqaspwK0/SUv826XIkA57pkjbqiT4ytrGJB+X5K0OB17/Ibz10wRSPKxIG3VPgQ ffVVuMmCbrFOMrsFfe7rHLyJ5TD32diLyudzSiwbLofrRXVYIB7Sw6XYq+cYpyxg8l0+ipFKJ3p VbwGhStpTLVoXkeqQSTDmlb3aI0eOMfZxvbAZkYztrC47LU/qNWsXGfKBAkEMbtjB6n2JtJswxu QgfUaOzyeidiegMOQtGUAwFb+P/LFAEi599ZfWaHITC1NfFmXkEZSj7f3H+jB1pdh5XEuEb9VOr 1Jyzk3nJyMRyx3rDmW78nAkOOzdKXdI9NpW1Yx/Lm/oz+5HTBQQ+FvDeONiASyxI57JwFKtYHab FemLqBcdG7sseYulaTUM5YVCJV9gl6odRIksUWcWCZhzZD+MiHtgJRJGVMHMdWoBjwcFf9TploA fTA3rE99on9hhsN6tioPeHCKF+jDxsy43DimavpKfqMWuZiXANk04ZBvrXuXBlaW+wan7m+/RDh KoWbpKHA/kUUnNQ== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 A caller that owns rpcbind must know what to register. It cannot work that out for itself: nfsd_support_acl_version() reads nfsd_acl_version[], which CONFIG_NFSD_V2_ACL and CONFIG_NFSD_V3_ACL build, and no netlink command reports that. Reply to a listener_set that carried userspace-rpcbind with the programs and versions that nfsd would have registered, plus the listeners to register them for. Send the reply only when the request asked for it, so an older caller still gets a bare ack. Assisted-by: LLM Signed-off-by: Jeff Layton --- fs/nfsd/nfsctl.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++= ++++ fs/nfsd/nfsd.h | 2 + fs/nfsd/nfssvc.c | 53 +++++++++++++-------- 3 files changed, 175 insertions(+), 19 deletions(-) diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 63746334a46f..102149aac2b6 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -2079,6 +2079,128 @@ static int nfsd_nl_validate_listeners(struct genl_i= nfo *info) return 0; } =20 +static size_t nfsd_nl_listener_set_msgsize(struct svc_serv *serv) +{ + size_t size =3D GENL_HDRLEN + /* genlmsg_iput() */ + nla_total_size(0); /* userspace-rpcbind */ + struct svc_xprt *xprt; + unsigned int p; + + lockdep_assert_held(&nfsd_mutex); + + for (p =3D 0; p < serv->sv_nprogs; p++) + size +=3D serv->sv_programs[p].pg_nvers * + (nla_total_size(0) + /* rpcbind nest */ + nla_total_size(sizeof(u32)) + /* program */ + nla_total_size(sizeof(u32)) + /* version */ + nla_total_size(sizeof(u32))); /* flags */ + + spin_lock_bh(&serv->sv_lock); + list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list) { + if (!test_bit(XPT_RPCB_UNREG, &xprt->xpt_flags)) + continue; + size +=3D nla_total_size(0) + /* addr nest */ + nla_total_size(strlen(xprt->xpt_class->xcl_name) + 1) + + nla_total_size(sizeof(struct sockaddr_storage)); + } + spin_unlock_bh(&serv->sv_lock); + + return size; +} + +static struct sk_buff * +nfsd_nl_listener_set_msg(struct genl_info *info, struct net *net, + struct svc_serv *serv) +{ + struct svc_xprt *xprt; + struct sk_buff *skb; + unsigned int p, i; + void *hdr; + int err; + + lockdep_assert_held(&nfsd_mutex); + + skb =3D genlmsg_new(nfsd_nl_listener_set_msgsize(serv), GFP_KERNEL); + if (!skb) + return ERR_PTR(-ENOMEM); + + hdr =3D genlmsg_iput(skb, info); + if (!hdr) { + err =3D -EMSGSIZE; + goto err_free_msg; + } + + if (nla_put_flag(skb, NFSD_A_SERVER_SOCK_USERSPACE_RPCBIND)) { + err =3D -EMSGSIZE; + goto err_free_msg; + } + + for (p =3D 0; p < serv->sv_nprogs; p++) { + const struct svc_program *progp =3D &serv->sv_programs[p]; + + for (i =3D 0; i < progp->pg_nvers; i++) { + struct nlattr *attr; + u32 flags =3D 0; + + if (!nfsd_version_registerable(net, progp, i)) + continue; + + if (progp->pg_vers[i]->vs_need_cong_ctrl) + flags |=3D NFSD_RPCBIND_FLAGS_NO_UDP; + + attr =3D nla_nest_start(skb, NFSD_A_SERVER_SOCK_RPCBIND); + if (!attr) { + err =3D -EMSGSIZE; + goto err_free_msg; + } + if (nla_put_u32(skb, NFSD_A_RPCBIND_PROGRAM, + progp->pg_prog) || + nla_put_u32(skb, NFSD_A_RPCBIND_VERSION, i) || + (flags && nla_put_u32(skb, NFSD_A_RPCBIND_FLAGS, + flags))) { + err =3D -EMSGSIZE; + goto err_free_msg; + } + nla_nest_end(skb, attr); + } + } + + spin_lock_bh(&serv->sv_lock); + list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list) { + struct nlattr *attr; + + if (!test_bit(XPT_RPCB_UNREG, &xprt->xpt_flags)) + continue; + + attr =3D nla_nest_start(skb, NFSD_A_SERVER_SOCK_ADDR); + if (!attr) { + err =3D -EMSGSIZE; + goto err_serv_unlock; + } + + if (nla_put_string(skb, NFSD_A_SOCK_TRANSPORT_NAME, + xprt->xpt_class->xcl_name) || + nla_put(skb, NFSD_A_SOCK_ADDR, + sizeof(struct sockaddr_storage), + &xprt->xpt_local)) { + err =3D -EMSGSIZE; + goto err_serv_unlock; + } + + nla_nest_end(skb, attr); + } + spin_unlock_bh(&serv->sv_lock); + + genlmsg_end(skb, hdr); + return skb; + +err_serv_unlock: + spin_unlock_bh(&serv->sv_lock); +err_free_msg: + nlmsg_free(skb); + return ERR_PTR(err); +} + /** * nfsd_nl_listener_set_doit - set the nfs running sockets * @skb: reply buffer @@ -2092,6 +2214,7 @@ int nfsd_nl_listener_set_doit(struct sk_buff *skb, st= ruct genl_info *info) const struct nlattr *bad_attr =3D NULL; struct svc_xprt *xprt, *tmp; const char *bad_xprt =3D NULL; + struct sk_buff *rskb =3D NULL; unsigned int rpcb_failures; const struct nlattr *attr; bool skipped_rpcb =3D false; @@ -2273,12 +2396,28 @@ int nfsd_nl_listener_set_doit(struct sk_buff *skb, = struct genl_info *info) "rpcbind did not answer, some listeners are not registered"); } =20 + /* + * Build the reply before the serv can go away, and only on success. + * A caller that got an errno has nothing to register. + */ + if (!err && userspace_rpcbind) { + rskb =3D nfsd_nl_listener_set_msg(info, net, serv); + if (IS_ERR(rskb)) { + err =3D PTR_ERR(rskb); + rskb =3D NULL; + } + } + if (!serv->sv_nrthreads && list_empty(&nn->nfsd_serv->sv_permsocks)) nfsd_destroy_serv(net); =20 out_unlock_mtx: mutex_unlock(&nfsd_mutex); =20 + /* rskb is only built once err is known to be zero. */ + if (rskb) + return genlmsg_reply(rskb, info); + return err; } =20 diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h index dcce45d58322..69e3e92b3ec1 100644 --- a/fs/nfsd/nfsd.h +++ b/fs/nfsd/nfsd.h @@ -117,6 +117,8 @@ extern const struct svc_version localio_version1; =20 enum vers_op {NFSD_SET, NFSD_CLEAR, NFSD_TEST, NFSD_AVAIL }; int nfsd_vers(struct nfsd_net *nn, int vers, enum vers_op change); +bool nfsd_version_registerable(struct net *net, + const struct svc_program *progp, u32 version); int nfsd_minorversion(struct nfsd_net *nn, u32 minorversion, enum vers_op = change); void nfsd_reset_versions(struct nfsd_net *nn); int nfsd_create_serv(struct net *net, bool no_rpcbind); diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index ef520d0562d6..890458c08f2e 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -41,11 +41,6 @@ atomic_t nfsd_th_cnt =3D ATOMIC_INIT(0); static int nfsd(void *vrqstp); #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) -static int nfsd_acl_rpcbind_set(struct net *, - const struct svc_program *, - u32, int, - unsigned short, - unsigned short); static __be32 nfsd_acl_init_request(struct svc_rqst *, const struct svc_program *, struct svc_process_info *); @@ -127,7 +122,7 @@ struct svc_program nfsd_programs[] =3D { .pg_class =3D "nfsd", .pg_authenticate =3D svc_set_client, .pg_init_request =3D nfsd_acl_init_request, - .pg_rpcbind_set =3D nfsd_acl_rpcbind_set, + .pg_rpcbind_set =3D nfsd_rpcbind_set, }, #endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */ #if IS_ENABLED(CONFIG_NFS_LOCALIO) @@ -813,18 +808,6 @@ nfsd_support_acl_version(int vers) return false; } =20 -static int -nfsd_acl_rpcbind_set(struct net *net, const struct svc_program *progp, - u32 version, int family, unsigned short proto, - unsigned short port) -{ - if (!nfsd_support_acl_version(version) || - !nfsd_vers(net_generic(net, nfsd_net_id), version, NFSD_TEST)) - return 0; - return svc_generic_rpcbind_set(net, progp, version, family, - proto, port); -} - static __be32 nfsd_acl_init_request(struct svc_rqst *rqstp, const struct svc_program *progp, @@ -859,12 +842,44 @@ nfsd_acl_init_request(struct svc_rqst *rqstp, } #endif =20 +/** + * nfsd_version_registerable - would nfsd register [@progp, @version]? + * @net: network namespace to query + * @progp: RPC program to query + * @version: RPC version to query + * + * Answers the question for a listener of any protocol. A caller that asks + * about one listener must apply vs_need_cong_ctrl itself. + * + * Return: true when the version is a candidate for rpcbind registration. + */ +bool nfsd_version_registerable(struct net *net, + const struct svc_program *progp, u32 version) +{ + struct nfsd_net *nn =3D net_generic(net, nfsd_net_id); + + if (version >=3D progp->pg_nvers || !progp->pg_vers[version]) + return false; + + /* nfslocalio is hidden and never reaches rpcbind. */ + if (progp->pg_vers[version]->vs_hidden) + return false; + +#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) + if (progp->pg_prog =3D=3D NFS_ACL_PROGRAM && + !nfsd_support_acl_version(version)) + return false; +#endif + + return nfsd_vers(nn, version, NFSD_TEST); +} + static int nfsd_rpcbind_set(struct net *net, const struct svc_program *progp, u32 version, int family, unsigned short proto, unsigned short port) { - if (!nfsd_vers(net_generic(net, nfsd_net_id), version, NFSD_TEST)) + if (!nfsd_version_registerable(net, progp, version)) return 0; return svc_generic_rpcbind_set(net, progp, version, family, proto, port); --=20 2.55.0 From nobody Fri Sep 25 16:03:02 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 71135582BA5; Thu, 10 Sep 2026 18:00:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789063261; cv=none; b=kqlojJ6uRAg3QeDQ9zYGRvNzcbVNC+MpxER6mf9FMYGjE2PdAGDhCpkhe/uivWFoX8f5egkRuBbmvinHHBkMkz3mOiUAkmnCW/1Q0hl8V15xnLcgEZ2kh+i9Ht7+Y/neHCDJb9JRdmncB8OVH0KPguuc/xQn5OC+6OmjE2uNMJM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789063261; c=relaxed/simple; bh=/ahQTbHtkmXc0vVtpv5rFUws88TJMKDVz4HzNdfcDC8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=VXnxubsuqlkJdMcj1jIYQ8emOuZsPsXcB0nFArrzjUGDpqHUaZdkOtAes0wbwpXyQ/UGHaubVTR3ZQKbdIeTnpGvHt3GdTKTYzm2a7SPCM1yN37xF7Zso7BG+3HpGBY9PTPFIoYfKB3ZL3NQiGB7kFCwNRTA1HCpSrC0FFy+cYg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=IIAj48mH; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="IIAj48mH" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 98FE31F00893; Thu, 10 Sep 2026 18:00:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1789063259; bh=JwFBOCwRWWpE4JTW9YlYjZhziYvJsFQmmybzwVleQPY=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=IIAj48mHz0vitv6ZMpc48JmRwjLWtfMepdzJo/ZELxYnkVW/QtI0YYAnu8aoKfPzz SZNCgBioM3ZvgRbIJjv4F+Ih1v/zw+bOS2AT0j9BYrj6N+V2TIjVWYpXg7M6T5CUnN iP57hrnmOvpoaSj/dHmMM5dkI5ArQxESFQ6jpE4smRzwjdOrjrpKk2dsM1Ieu/r+qB 6F4gATniEfpNEM31bmEhZl0BBXGiblqUUa1ZjJC99SIiSm2W/FfrX31DVb0aV0ZlTZ JaQ8oVYNmkey1DtYGfTnb1as0KsZ4rinCcaCXU9S125QhgItSShLFO0jyFD5CJhhzD AyAJg3rFOt0Fg== From: Jeff Layton Date: Thu, 10 Sep 2026 14:00:38 -0400 Subject: [PATCH 5/5] selftests/nfsd: exercise the userspace-rpcbind listener_set flag Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260910-nfsd-norpcb-v1-5-b4d5182d634c@kernel.org> References: <20260910-nfsd-norpcb-v1-0-b4d5182d634c@kernel.org> In-Reply-To: <20260910-nfsd-norpcb-v1-0-b4d5182d634c@kernel.org> To: Trond Myklebust , Anna Schumaker , Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Donald Hunter , Shuah Khan Cc: linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, linux-kselftest@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=12049; i=jlayton@kernel.org; h=from:subject:message-id; bh=/ahQTbHtkmXc0vVtpv5rFUws88TJMKDVz4HzNdfcDC8=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBqovBR8oltwDYgNnAyYAdEcoA2jQDsWRQTDDSEz n8gOwv50RmJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaqLwUQAKCRAADmhBGVaC FV/lD/wOlZ8uMGKjBkIdU2xsFRUIw8+G6kgRhy+I024fNcBL0wDcYPQIBV7B9NoJOxGB0SHc7uX Q4cR1d7rx76pybTA4QK19T4z16UG8exqA5D8Ky7e6daII/B5oJJ5zxoeQ5d5kBtHVo5A+cK1XVS p5EORhjumYI53I+RrfVC82Oja5EKDuK2tNhAnALt1zKD1KRsk6RPUfU9+UFWO6ZIZNCKfYuPcH7 gNYRjGyfZReA3wiTo3lTs32PE8SqlYD6qTRFJEgoh2HCmAUjMah8jrkXHi42fCcrBnY5z6ta1q7 z1DfB+nrZcRLCqR0MORQuYPRDMVzSKtECw+t11gMT+cKmUTClxilHzm89yiNeM/mUt0fh7ee2/K tarVfWYf3SKvKANwlYNhsFK4/YBT+Sz2thghsG+jo0b8CLfOK6O+Q40U1yx5xfubazJNSusAbrt Ruko/cyWCq9x5QyjE78gCUyTIewPAvef/9Ocy8mfxgm3dyo+wE0Mv3Zi3IC1HGO1oFnUiAtZaM6 9RX8nE7zyDU6Bm8n4dlY/1t+daYEA70bQvWF/MjzsDC4qswXy40YQm3rQrYH4rEqdK3KCfwouY+ dWOb5NCkpdDHkLaKY/fx6JF3/+qp6LS524iv+YQqxGws+UZ8kWvYPKQF7hMY7jwoDe+SiJIPjrr Kxbe1MDAsDx/IEA== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 Cover the flag that moves rpcbind registration to the caller. rpcb_userspace_no_traffic is the one that matters. The errno says nothing about whether the kernel talked to rpcbind, but the stub counters do: a request that carries the flag must leave both at zero, which is what shows that svc_bind() and svc_register() were both skipped. The rest cover the reply and the ownership rule: - rpcb_userspace_reply. The ack flag, a non-empty program list, and the listener that came up. nfslocalio is hidden, so it must be absent. - rpcb_userspace_no_v4_udp. NFSv4 carries no-udp and NFSv3 does not. - rpcb_userspace_nfsacl_follows_nfs. CONFIG_NFSD_V3_ACL is invisible to the test, so assert only that nfsacl v3 implies nfs v3. - rpcb_userspace_busy and rpcb_userspace_busy_reverse. Ownership cannot change under a live serv, in either direction. - rpcb_userspace_teardown. Create and destroy a flagged serv three times, then confirm that a kernel-owned serv still reaches rpcbind. An unbalanced rpcb_put_local() would break the last step. - rpcb_userspace_many_listeners. Forty listeners, which is more than GENLMSG_DEFAULT_SIZE would have held. A reply sized from that constant instead of from its contents returns -EMSGSIZE with every listener already up. genl_request_reply() grew an attribute argument, because listener_set now answers with a reply message rather than a bare ack. Assisted-by: LLM Signed-off-by: Jeff Layton --- .../testing/selftests/nfsd/nfsd_netlink_listener.c | 284 +++++++++++++++++= +++- 1 file changed, 281 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/nfsd/nfsd_netlink_listener.c b/tools/t= esting/selftests/nfsd/nfsd_netlink_listener.c index 106360f87b99..56ac2c11c07f 100644 --- a/tools/testing/selftests/nfsd/nfsd_netlink_listener.c +++ b/tools/testing/selftests/nfsd/nfsd_netlink_listener.c @@ -46,6 +46,9 @@ =20 #include "../kselftest_harness.h" =20 +#define NFS_PROGRAM 100003 +#define NFS_ACL_PROGRAM 100227 + #define NLA_ALIGN4(len) (((len) + 3) & ~3) #define TEST_PORT 20049 #define MAX_LISTENERS 8 @@ -173,15 +176,24 @@ static int genl_request(uint8_t cmd, const char *attr= s, int attrs_len) return ret; } =20 -/* Send a command and return the full reply message; -errno on failure. */ -static int genl_request_reply(uint8_t cmd, char *rbuf, size_t rlen) +/* + * Send a command with attributes and return the full reply message; -errno + * on failure. NLM_F_ACK is left off: the kernel reports an error either w= ay, + * so the first message back is the reply whenever there is one. + */ +static int genl_request_reply_attrs(uint8_t cmd, const char *attrs, + int attrs_len, char *rbuf, size_t rlen) { - char buf[256]; + char buf[1 << 20]; struct nlmsghdr *nlh =3D (void *)buf; int fd =3D genl_open(); int off, n, ret; =20 off =3D genl_hdr(buf, nfsd_family, NLM_F_REQUEST, cmd); + if (attrs_len) { + memcpy(buf + off, attrs, attrs_len); + off +=3D attrs_len; + } nlh->nlmsg_len =3D off; =20 if (send(fd, buf, off, 0) < 0) @@ -198,6 +210,11 @@ static int genl_request_reply(uint8_t cmd, char *rbuf,= size_t rlen) return ret; } =20 +static int genl_request_reply(uint8_t cmd, char *rbuf, size_t rlen) +{ + return genl_request_reply_attrs(cmd, NULL, 0, rbuf, rlen); +} + /* Resolve the "nfsd" genl family id; -1 if not registered. */ static int genl_resolve_nfsd(void) { @@ -383,6 +400,111 @@ static int version_set_only(uint32_t major, uint32_t = minor) return genl_request(NFSD_CMD_VERSION_SET, attrs, NLA_ALIGN4(inner)); } =20 +/* ------------------- userspace-rpcbind ------------------- */ + +struct rpcb_ent { + uint32_t program; + uint32_t version; + uint32_t flags; +}; + +/* More listeners than GENLMSG_DEFAULT_SIZE would have held. */ +#define RPCB_MANY_LISTENERS 40 + +struct rpcb_reply { + int acked; /* saw NFSD_A_SERVER_SOCK_USERSPACE_RPCBIND */ + int nprog; + struct rpcb_ent prog[16]; + int naddr; /* every addr nest, not just the stored ones */ + int nlistener; + struct listener_ent listener[MAX_LISTENERS]; +}; + +/* Append the userspace-rpcbind request flag. */ +static int put_userspace_rpcbind(char *buf, int off) +{ + return put_attr(buf, off, NFSD_A_SERVER_SOCK_USERSPACE_RPCBIND, NULL, 0); +} + +static void parse_rpcb_nest(const struct nlattr *na, struct rpcb_ent *e) +{ + const struct nlattr *in =3D (const void *)((const char *)na + NLA_HDRLEN); + int ileft =3D na->nla_len - NLA_HDRLEN; + + memset(e, 0, sizeof(*e)); + while (ileft >=3D (int)NLA_HDRLEN) { + const void *d =3D (const char *)in + NLA_HDRLEN; + + switch (in->nla_type & NLA_TYPE_MASK) { + case NFSD_A_RPCBIND_PROGRAM: + e->program =3D *(const uint32_t *)d; + break; + case NFSD_A_RPCBIND_VERSION: + e->version =3D *(const uint32_t *)d; + break; + case NFSD_A_RPCBIND_FLAGS: + e->flags =3D *(const uint32_t *)d; + break; + } + ileft -=3D NLA_ALIGN4(in->nla_len); + in =3D (const void *)((const char *)in + NLA_ALIGN4(in->nla_len)); + } +} + +/* + * Send a listener_set that asks to own rpcbind, and parse the reply. + * Returns 0 on success or -errno. + */ +static int listener_set_rpcb(char *attrs, int off, struct rpcb_reply *out) +{ + char rbuf[64 * 1024]; + const struct nlmsghdr *nlh =3D (const void *)rbuf; + const struct nlattr *na; + int left, n; + + off =3D put_userspace_rpcbind(attrs, off); + memset(out, 0, sizeof(*out)); + + n =3D genl_request_reply_attrs(NFSD_CMD_LISTENER_SET, attrs, off, + rbuf, sizeof(rbuf)); + if (n < 0) + return n; + + out->nlistener =3D parse_listener_get(rbuf, n, out->listener, + MAX_LISTENERS); + + na =3D (const void *)(rbuf + NLMSG_HDRLEN + GENL_HDRLEN); + left =3D nlh->nlmsg_len - NLMSG_HDRLEN - GENL_HDRLEN; + while (left >=3D (int)NLA_HDRLEN) { + switch (na->nla_type & NLA_TYPE_MASK) { + case NFSD_A_SERVER_SOCK_USERSPACE_RPCBIND: + out->acked =3D 1; + break; + case NFSD_A_SERVER_SOCK_ADDR: + out->naddr++; + break; + case NFSD_A_SERVER_SOCK_RPCBIND: + if (out->nprog < (int)ARRAY_SIZE(out->prog)) + parse_rpcb_nest(na, &out->prog[out->nprog++]); + break; + } + left -=3D NLA_ALIGN4(na->nla_len); + na =3D (const void *)((const char *)na + NLA_ALIGN4(na->nla_len)); + } + return 0; +} + +static struct rpcb_ent *find_rpcb(struct rpcb_reply *r, uint32_t prog, + uint32_t vers) +{ + int i; + + for (i =3D 0; i < r->nprog; i++) + if (r->prog[i].program =3D=3D prog && r->prog[i].version =3D=3D vers) + return &r->prog[i]; + return NULL; +} + /* Fetch the current listeners; returns count (>=3D0) or -errno. */ static int listener_get(struct listener_ent *out, int max) { @@ -1282,6 +1404,162 @@ TEST_F(nfsd_listener, rpcb_unreg_stop_after_failure) EXPECT_LE(three, one); } =20 +/* =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D userspa= ce rpcbind =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D = */ + +/* + * The point of the flag: nfsd must make no rpcbind call at all. svc_bind() + * pings rpcbind at client creation and svc_register() calls it once per + * program and version, so a silent stub is what proves both were skipped. + */ +TEST_F(nfsd_listener, rpcb_userspace_no_traffic) +{ + struct rpcb_reply r; + char attrs[64]; + int off =3D put_listener(attrs, 0, "tcp", TEST_PORT); + + ASSERT_EQ(0, rpcb_conns()); + ASSERT_EQ(0, listener_set_rpcb(attrs, off, &r)); + EXPECT_EQ(0, rpcb_conns()); + EXPECT_EQ(0, rpcb_calls()); +} + +/* + * The reply has to tell the caller what to register. Without the program + * list it cannot know whether nfsacl is built in. + */ +TEST_F(nfsd_listener, rpcb_userspace_reply) +{ + struct rpcb_reply r; + char attrs[64]; + int off =3D put_listener(attrs, 0, "tcp", TEST_PORT); + + ASSERT_EQ(0, listener_set_rpcb(attrs, off, &r)); + EXPECT_EQ(1, r.acked); + EXPECT_GT(r.nprog, 0); + /* the listener came up and is named, so the caller knows the port */ + ASSERT_EQ(1, r.nlistener); + EXPECT_NE(NULL, find_listener(r.listener, r.nlistener, "tcp", + AF_INET, TEST_PORT)); + /* nfslocalio is hidden and must never be offered for registration */ + EXPECT_EQ(NULL, find_rpcb(&r, 400122, 1)); +} + +/* + * nfsd_nl_validate_listeners() allows far more listeners than the default + * genl buffer holds, so the reply has to be sized from its contents. If it + * is not, the listeners all come up and the caller still sees -EMSGSIZE. + */ +TEST_F(nfsd_listener, rpcb_userspace_many_listeners) +{ + char attrs[RPCB_MANY_LISTENERS * 64]; + struct rpcb_reply r; + int off =3D 0, i; + + for (i =3D 0; i < RPCB_MANY_LISTENERS; i++) + off =3D put_listener(attrs, off, "tcp", TEST_PORT + i); + + ASSERT_EQ(0, listener_set_rpcb(attrs, off, &r)); + EXPECT_EQ(1, r.acked); + EXPECT_GT(r.nprog, 0); + EXPECT_EQ(RPCB_MANY_LISTENERS, r.naddr); +} + +/* + * NFSv4 sets vs_need_cong_ctrl, so the kernel never registered it on UDP. + * The reply cannot filter it out, because the rule depends on the listene= r, + * so it must carry the flag instead. + */ +TEST_F(nfsd_listener, rpcb_userspace_no_v4_udp) +{ + struct rpcb_ent *v4, *v3; + struct rpcb_reply r; + char attrs[64]; + int off =3D put_listener(attrs, 0, "tcp", TEST_PORT); + + ASSERT_EQ(0, listener_set_rpcb(attrs, off, &r)); + + v4 =3D find_rpcb(&r, NFS_PROGRAM, 4); + if (v4) + EXPECT_EQ(NFSD_RPCBIND_FLAGS_NO_UDP, + v4->flags & NFSD_RPCBIND_FLAGS_NO_UDP); + + v3 =3D find_rpcb(&r, NFS_PROGRAM, 3); + if (v3) + EXPECT_EQ(0, v3->flags & NFSD_RPCBIND_FLAGS_NO_UDP); +} + +/* + * nfsacl is the value userland cannot derive: CONFIG_NFSD_V3_ACL is not + * visible over netlink. Only assert self-consistency -- if the kernel + * offers nfsacl v3 then it must also offer nfs v3, since both gate on the + * same enabled version. + */ +TEST_F(nfsd_listener, rpcb_userspace_nfsacl_follows_nfs) +{ + struct rpcb_reply r; + char attrs[64]; + int off =3D put_listener(attrs, 0, "tcp", TEST_PORT); + + ASSERT_EQ(0, listener_set_rpcb(attrs, off, &r)); + if (find_rpcb(&r, NFS_ACL_PROGRAM, 3)) + EXPECT_NE(NULL, find_rpcb(&r, NFS_PROGRAM, 3)); +} + +/* + * svc_bind() decided whether to take the rpcb_users reference that teardo= wn + * drops, so ownership cannot flip under a live serv. + */ +TEST_F(nfsd_listener, rpcb_userspace_busy) +{ + struct rpcb_reply r; + char attrs[64], plain[64]; + int off =3D put_listener(attrs, 0, "tcp", TEST_PORT); + int poff =3D put_listener(plain, 0, "tcp", TEST_PORT); + + ASSERT_EQ(0, listener_set_rpcb(attrs, off, &r)); + + /* same listeners, but now asking the kernel to own rpcbind */ + EXPECT_EQ(-EBUSY, listener_set(plain, poff)); + EXPECT_STRNE("", last_extack); +} + +/* And the same the other way round. */ +TEST_F(nfsd_listener, rpcb_userspace_busy_reverse) +{ + struct rpcb_reply r; + char attrs[64], plain[64]; + int poff =3D put_listener(plain, 0, "tcp", TEST_PORT); + int off =3D put_listener(attrs, 0, "tcp", TEST_PORT); + + ASSERT_EQ(0, listener_set(plain, poff)); + EXPECT_EQ(-EBUSY, listener_set_rpcb(attrs, off, &r)); +} + +/* + * rpcb_create_local() increments sn->rpcb_users and rpcb_put_local() + * decrements it. A serv that never took the reference must not drop it, or + * the next serv finds the count wrong. Cycle a few times, then confirm a + * kernel-owned serv can still reach rpcbind. + */ +TEST_F(nfsd_listener, rpcb_userspace_teardown) +{ + struct rpcb_reply r; + char attrs[64], plain[64]; + int off, poff, i; + + for (i =3D 0; i < 3; i++) { + off =3D put_listener(attrs, 0, "tcp", TEST_PORT); + ASSERT_EQ(0, listener_set_rpcb(attrs, off, &r)); + /* empty list with no threads destroys the serv */ + ASSERT_EQ(0, listener_set_rpcb(attrs, 0, &r)); + ASSERT_EQ(0, rpcb_conns()); + } + + poff =3D put_listener(plain, 0, "tcp", TEST_PORT); + ASSERT_EQ(0, listener_set(plain, poff)); + EXPECT_GT(rpcb_conns(), 0); +} + /* =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D threads= / -EBUSY semantics =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D */ =20 TEST_F(nfsd_listener, sem_busy_on_change) --=20 2.55.0