From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: stable@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
patches@lists.linux.dev, Jeff Layton <jlayton@kernel.org>,
Chuck Lever <cel@kernel.org>, Sasha Levin <sashal@kernel.org>
Subject: [PATCH 6.18 042/686] SUNRPC: report local rpcbind calls that get no answer
Date: Fri, 13 Nov 2026 10:42:55 -0500 [thread overview]
Message-ID: <20261113153822.390728449@linuxfoundation.org> (raw)
In-Reply-To: <20261113153820.902362109@linuxfoundation.org>
6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeff Layton <jlayton@kernel.org>
[ Upstream commit 202a557d0c8e65c7fd7fcff2ad2756468d1ab711 ]
A caller that creates many listeners in one operation calls svc_register()
once for each of them. Every call waits for the local rpcbind on its own,
so a rpcbind that never answers costs the caller one timeout per listener.
The caller has no way to learn that the first call already failed.
Split rpcb_register_call() failures by whether rpcbind answered:
- answered: a FALSE reply, or an RPC-level rejection that
rpc_decode_header() derives from the reply. -EACCES (FALSE reply or
AUTH_ERROR), -EPROTONOSUPPORT, -EPFNOSUPPORT, -EOPNOTSUPP.
- never sent: -ENOMEM, -EMSGSIZE, -ERESTARTSYS.
- no answer: everything else, i.e. transport errors.
Any no-answer error gets represented by -EIO, which is already what the
RPC layer reports for most of it: rpc_check_timeout() returns -EIO for a
soft timeout without RPC_TASK_TIMEOUT, and call_status() documents -EIO
as "shutdown or soft timeout".
Keep a count of the number of rpcbind failures in the serv. Later
patches will use that to watch for hard rpcbind failures, and alter
their behavior accordingly.
Assisted-by: LLM
Signed-off-by: Jeff Layton <jlayton@kernel.org>
Link: https://patch.msgid.link/20260901-nfsd-nl-hang-v5-6-a540d86668b0@kernel.org
Signed-off-by: Chuck Lever <cel@kernel.org>
Stable-dep-of: bf0f3a37e6cc ("NFSD: stop registering with rpcbind after a failure in listener_set")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
include/linux/sunrpc/clnt.h | 3 ++-
include/linux/sunrpc/svc.h | 7 +++++--
net/sunrpc/rpcb_clnt.c | 22 ++++++++++++++++---
net/sunrpc/svc.c | 42 ++++++++++++++++++++++++++++++++++++-
4 files changed, 67 insertions(+), 7 deletions(-)
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 3c2b8c355ab3a..30344c0d6a9d7 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -199,7 +199,8 @@ struct rpc_xprt *rpc_task_get_xprt(struct rpc_clnt *clnt,
int rpcb_create_local(struct net *);
void rpcb_put_local(struct net *);
-int rpcb_register(struct net *, u32, u32, int, unsigned short);
+int rpcb_register(struct net *net, u32 prog, u32 vers, int prot,
+ unsigned short port);
int rpcb_v4_register(struct net *net, const u32 program,
const u32 version,
const struct sockaddr *address,
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 5506d20857c31..1668804db44dd 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -75,6 +75,7 @@ struct svc_serv {
unsigned int sv_max_payload; /* datagram payload size */
unsigned int sv_max_mesg; /* max_payload + 1 page for overheads */
unsigned int sv_xdrsize; /* XDR buffer size */
+ atomic_t sv_rpcb_failures; /* unanswered rpcbind calls */
struct list_head sv_permsocks; /* all permanent sockets */
struct list_head sv_tempsocks; /* all temporary sockets */
int sv_tmpcnt; /* count of temporary "valid" sockets */
@@ -435,6 +436,7 @@ int sunrpc_set_pool_mode(const char *val);
int sunrpc_get_pool_mode(char *val, size_t size);
void svc_rpcb_cleanup(struct svc_serv *serv, struct net *net);
int svc_bind(struct svc_serv *serv, struct net *net);
+unsigned int svc_rpcb_failure_count(struct svc_serv *serv);
struct svc_serv *svc_create(struct svc_program *, unsigned int,
int (*threadfn)(void *data));
bool svc_rqst_replace_page(struct svc_rqst *rqstp,
@@ -450,8 +452,9 @@ int svc_set_num_threads(struct svc_serv *, struct svc_pool *, int);
int svc_pool_stats_open(struct svc_info *si, struct file *file);
void svc_process(struct svc_rqst *rqstp);
void svc_process_bc(struct rpc_rqst *req, struct svc_rqst *rqstp);
-int svc_register(const struct svc_serv *, struct net *, const int,
- const unsigned short, const unsigned short);
+int svc_register(struct svc_serv *serv, struct net *net,
+ const int family, const unsigned short proto,
+ const unsigned short port);
void svc_wake_up(struct svc_serv *);
void svc_reserve(struct svc_rqst *rqstp, int space);
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index 2d74c660de666..9b90350820be4 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -400,7 +400,8 @@ static struct rpc_clnt *rpcb_create(struct net *net, const char *nodename,
return rpc_create(&args);
}
-static int rpcb_register_call(struct sunrpc_net *sn, struct rpc_clnt *clnt, struct rpc_message *msg, bool is_set)
+static int rpcb_register_call(struct sunrpc_net *sn, struct rpc_clnt *clnt,
+ struct rpc_message *msg, bool is_set)
{
int flags = RPC_TASK_NOCONNECT;
int error, result = 0;
@@ -410,8 +411,23 @@ static int rpcb_register_call(struct sunrpc_net *sn, struct rpc_clnt *clnt, stru
msg->rpc_resp = &result;
error = rpc_call_sync(clnt, msg, flags);
- if (error < 0)
- return error;
+ if (error < 0) {
+ switch (error) {
+ /* rpcbind answered; the reply itself carries the error */
+ case -EPROTONOSUPPORT:
+ case -EPFNOSUPPORT:
+ case -EOPNOTSUPP:
+ case -EACCES:
+ /* the call never made it onto the wire */
+ case -ENOMEM:
+ case -EMSGSIZE:
+ /* the caller is going away; this says nothing about rpcbind */
+ case -ERESTARTSYS:
+ return error;
+ }
+ /* anything else, we assume that rpcbind isn't functional */
+ return -EIO;
+ }
if (!result)
return -EACCES;
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index 61c3c3a743289..a3933f86f2d42 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -1207,10 +1207,40 @@ int svc_generic_rpcbind_set(struct net *net,
error = svc_rpcbind_set_version(net, progp, version,
family, proto, port);
+ /* -EIO means no answer, not a refusal, so vs_rpcb_optnl must keep it. */
+ if (error == -EIO)
+ return error;
+
return (vers->vs_rpcb_optnl) ? 0 : error;
}
EXPORT_SYMBOL_GPL(svc_generic_rpcbind_set);
+/**
+ * svc_rpcb_failure_count - local rpcbind calls for @serv that got no answer
+ * @serv: RPC service to query
+ *
+ * svc_register() adds one for each of its calls that got no answer. A reply
+ * that refuses one entry does not count, because rpcbind answered and the
+ * next entry may still succeed.
+ *
+ * The count is kept per serv rather than per net. The local rpcbind client
+ * is per-net and lockd shares it, but a count that another service can move
+ * says nothing about this serv's own calls.
+ *
+ * This is for callers that cannot see the svc_register() return, because a
+ * transport class sits in between. Such a caller reads the count before it
+ * starts and compares as it goes, so there is no state to reset between
+ * operations. The count never resets, and callers must not attach meaning
+ * to the value itself.
+ *
+ * Return: the number of unanswered calls since this serv was created.
+ */
+unsigned int svc_rpcb_failure_count(struct svc_serv *serv)
+{
+ return atomic_read(&serv->sv_rpcb_failures);
+}
+EXPORT_SYMBOL_GPL(svc_rpcb_failure_count);
+
/**
* svc_register - register an RPC service with the local portmapper
* @serv: svc_serv struct for the service to register
@@ -1221,10 +1251,11 @@ EXPORT_SYMBOL_GPL(svc_generic_rpcbind_set);
*
* Service is registered for any address in the passed-in protocol family
*/
-int svc_register(const struct svc_serv *serv, struct net *net,
+int svc_register(struct svc_serv *serv, struct net *net,
const int family, const unsigned short proto,
const unsigned short port)
{
+ bool noanswer = false;
unsigned int p, i;
int error = 0;
@@ -1236,10 +1267,16 @@ int svc_register(const struct svc_serv *serv, struct net *net,
struct svc_program *progp = &serv->sv_programs[p];
for (i = 0; i < progp->pg_nvers; i++) {
+ const struct svc_version *vers = progp->pg_vers[i];
int ret;
ret = progp->pg_rpcbind_set(net, progp, i,
family, proto, port);
+ if (ret == -EIO) {
+ noanswer = true;
+ if (vers && vers->vs_rpcb_optnl)
+ ret = 0;
+ }
if (ret < 0) {
printk(KERN_WARNING "svc: failed to register "
"%sv%u RPC service (errno %d).\n",
@@ -1251,6 +1288,9 @@ int svc_register(const struct svc_serv *serv, struct net *net,
}
}
+ if (noanswer)
+ atomic_inc(&serv->sv_rpcb_failures);
+
return error;
}
--
2.53.0
next prev parent reply other threads:[~2026-11-13 16:06 UTC|newest]
Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-13 15:42 [PATCH 6.18 000/686] 6.18.64-rc1 review Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 001/686] smb: client: validate the data area in SMB2_read() Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 002/686] ALSA: x86: hdmi: fix chmap array missing terminator entry Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 003/686] cxl/features: Ensure that count is set before access to ent[] __counted_by() Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 004/686] backing-file: always end a queued write Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 005/686] nvmet-rdma: fix out-of-bounds write in nvmet_rdma_map_sgl_inline() Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 006/686] crypto: sa2ul - Fix HMAC key preparation Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 007/686] fsverity: Tell LSMs about signature only after verity is enabled Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 008/686] Bluetooth: L2CAP: Reject signalling responses in invalid states Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 009/686] Bluetooth: L2CAP: Only accept connection responses to outstanding requests Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 010/686] Bluetooth: L2CAP: Ignore connection responses with wrong ident Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 011/686] smb: client: Avoid leaking sensitive data to the heap in connect.c Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 012/686] smb: client: hold server info until cifsd exits Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 013/686] smb: move smb_sockaddr_in and smb_sockaddr_in6 to common/smb2pdu.h Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 014/686] smb: move create_durable_req_v2 " Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 015/686] smb: move create_durable_handle_reconnect_v2 " Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 016/686] smb: move create_durable_rsp_v2 " Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 017/686] smb: move some duplicate definitions " Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 018/686] smb: move list of FileSystemAttributes to common/fscc.h Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 019/686] smb: move some duplicate struct definitions " Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 020/686] smb: client: fix OOB read of the resume name sent in TRANS2_FIND_NEXT2 Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 021/686] smb: client: fix OOB read in the SMB_FIND_FILE_UNIX name scan Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 022/686] smb: client: reject short SESSION_SETUP responses Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 023/686] smb: client: require stable pages for SMB compression Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 024/686] mm: remove !root_reclaim checking in should_abort_scan() Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 025/686] smb: client: validate SMB1 EA list bounds before parsing Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 026/686] xfs: break out xattr entry checks into separate functions Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 027/686] xfs: check for buffer overruns when examining local/remote xattr entries Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 028/686] xfs: refactor directory data block walking loops in scrub Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 029/686] xfs: improve dirent bounds checking in scrub and repair Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 030/686] NFSv4/pnfs: bound the CB_NOTIFY_DEVICEID array count before allocating Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 031/686] smb: client: bound POSIX lock data area by response length Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 032/686] smb: align durable reconnect v2 context to 8 byte boundary Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 033/686] NFSD: Replace nfsd_write()s "stable" argument with "iocb_flags" Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 034/686] NFSD: Move version-specific ACCESS maps into per-version code Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 035/686] NFSD: map fh_verify() status codes for NFS_ACLv2 replies Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 036/686] NFSD/blocklayout: Extract extent mapping from proc_layoutget Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 037/686] exportfs: Complete kernel-doc for struct export_operations Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 038/686] exportfs: split out the ops for layout-based block device access Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 039/686] exportfs,nfsd: rework checking for layout-based block device access support Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 040/686] nfsd: dont offer flexfiles layouts when NFSv3 isnt being served Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 041/686] NFSD: report listener creation failures through extack Greg Kroah-Hartman
2026-11-13 15:42 ` Greg Kroah-Hartman [this message]
2026-11-13 15:42 ` [PATCH 6.18 043/686] NFSD: stop registering with rpcbind after a failure in listener_set Greg Kroah-Hartman
2026-11-13 15:42 ` [PATCH 6.18 045/686] NFSD: Count the delegations held by each client Greg Kroah-Hartman
2026-11-13 15:43 ` [PATCH 6.18 054/686] KVM: TDX: Stuff exit_reason with UNDEFINED on wait_for_sept_zap return Greg Kroah-Hartman
2026-11-13 15:43 ` [PATCH 6.18 055/686] KVM: TDX: Set bits 31:16 to 0 and use UNDEFINED when synthesizing exit reason Greg Kroah-Hartman
2026-11-13 15:43 ` [PATCH 6.18 056/686] KVM: TDX: Dont assume exit_reason[31:16] is all-0 in tdx_to_vmx_exit_reason() Greg Kroah-Hartman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261113153822.390728449@linuxfoundation.org \
--to=gregkh@linuxfoundation.org \
--cc=cel@kernel.org \
--cc=jlayton@kernel.org \
--cc=patches@lists.linux.dev \
--cc=sashal@kernel.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox