From: Chuck Lever <cel@kernel.org>
To: NeilBrown <neilb@ownmail.net>, Jeff Layton <jlayton@kernel.org>,
Olga Kornievskaia <okorniev@redhat.com>,
Dai Ngo <dai.ngo@oracle.com>, Tom Talpey <tom@talpey.com>
Cc: <linux-nfs@vger.kernel.org>, Chuck Lever <chuck.lever@oracle.com>
Subject: [PATCH v4 06/14] NFS: Use nlmclnt_shutdown_rpc_clnt() to safely shut down NLM
Date: Wed, 28 Jan 2026 10:19:27 -0500 [thread overview]
Message-ID: <20260128151935.1646063-7-cel@kernel.org> (raw)
In-Reply-To: <20260128151935.1646063-1-cel@kernel.org>
From: Chuck Lever <chuck.lever@oracle.com>
A race condition exists in shutdown_store() when writing to the sysfs
"shutdown" file concurrently with nlm_shutdown_hosts_net(). Without
synchronization, the following sequence can occur:
1. shutdown_store() reads server->nlm_host (non-NULL)
2. nlm_shutdown_hosts_net() acquires nlm_host_mutex, calls
rpc_shutdown_client(), sets h_rpcclnt to NULL, and potentially
frees the host via nlm_gc_hosts()
3. shutdown_store() dereferences the now-stale or freed host
Introduce nlmclnt_shutdown_rpc_clnt(), which acquires nlm_host_mutex
before accessing h_rpcclnt. This synchronizes with
nlm_shutdown_hosts_net() and ensures the rpc_clnt pointer remains
valid during the shutdown operation.
This change also improves API layering: NFS client code no longer
needs to include the internal lockd header to access nlm_host fields.
The new helper resides in bind.h alongside other public lockd
interfaces.
Reported-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/lockd/host.c | 29 +++++++++++++++++++++++++++++
fs/nfs/sysfs.c | 4 ++--
include/linux/lockd/bind.h | 1 +
3 files changed, 32 insertions(+), 2 deletions(-)
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 5e6877c37f73..87c88a8f9902 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -306,6 +306,35 @@ void nlmclnt_release_host(struct nlm_host *host)
}
}
+/* Callback for rpc_cancel_tasks() - matches all tasks for cancellation */
+static bool nlmclnt_match_all(const struct rpc_task *task, const void *data)
+{
+ return true;
+}
+
+/**
+ * nlmclnt_shutdown_rpc_clnt - safely shut down NLM client RPC operations
+ * @host: nlm_host to shut down
+ *
+ * Cancels outstanding RPC tasks and marks the client as shut down.
+ * Synchronizes with nlmclnt_release_host() via nlm_host_mutex to prevent
+ * races between shutdown and host destruction. Safe to call if h_rpcclnt
+ * is NULL or already shut down.
+ */
+void nlmclnt_shutdown_rpc_clnt(struct nlm_host *host)
+{
+ struct rpc_clnt *clnt;
+
+ mutex_lock(&nlm_host_mutex);
+ clnt = host->h_rpcclnt;
+ if (clnt) {
+ clnt->cl_shutdown = 1;
+ rpc_cancel_tasks(clnt, -EIO, nlmclnt_match_all, NULL);
+ }
+ mutex_unlock(&nlm_host_mutex);
+}
+EXPORT_SYMBOL_GPL(nlmclnt_shutdown_rpc_clnt);
+
/**
* nlmsvc_lookup_host - Find an NLM host handle matching a remote client
* @rqstp: incoming NLM request
diff --git a/fs/nfs/sysfs.c b/fs/nfs/sysfs.c
index ea6e6168092b..008b3decde24 100644
--- a/fs/nfs/sysfs.c
+++ b/fs/nfs/sysfs.c
@@ -12,7 +12,7 @@
#include <linux/string.h>
#include <linux/nfs_fs.h>
#include <linux/rcupdate.h>
-#include <linux/lockd/lockd.h>
+#include <linux/lockd/bind.h>
#include "internal.h"
#include "nfs4_fs.h"
@@ -285,7 +285,7 @@ shutdown_store(struct kobject *kobj, struct kobj_attribute *attr,
shutdown_client(server->client_acl);
if (server->nlm_host)
- shutdown_client(server->nlm_host->h_rpcclnt);
+ nlmclnt_shutdown_rpc_clnt(server->nlm_host);
out:
shutdown_nfs_client(server->nfs_client);
return count;
diff --git a/include/linux/lockd/bind.h b/include/linux/lockd/bind.h
index 82eca0a13ccc..39c124dcb19c 100644
--- a/include/linux/lockd/bind.h
+++ b/include/linux/lockd/bind.h
@@ -57,6 +57,7 @@ struct nlmclnt_initdata {
extern struct nlm_host *nlmclnt_init(const struct nlmclnt_initdata *nlm_init);
extern void nlmclnt_done(struct nlm_host *host);
extern struct rpc_clnt *nlmclnt_rpc_clnt(struct nlm_host *host);
+extern void nlmclnt_shutdown_rpc_clnt(struct nlm_host *host);
/*
* NLM client operations provide a means to modify RPC processing of NLM
--
2.52.0
next prev parent reply other threads:[~2026-01-28 15:19 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-28 15:19 [PATCH v4 00/14] Subject: Clarify module API boundaries Chuck Lever
2026-01-28 15:19 ` [PATCH v4 01/14] lockd: Simplify cast_status() in svcproc.c Chuck Lever
2026-01-28 15:19 ` [PATCH v4 02/14] lockd: Relocate and rename nlm_drop_reply Chuck Lever
2026-01-28 15:19 ` [PATCH v4 03/14] lockd: Introduce nlm__int__deadlock Chuck Lever
2026-01-28 15:19 ` [PATCH v4 04/14] lockd: Have nlm_fopen() return errno values Chuck Lever
2026-01-28 15:19 ` [PATCH v4 05/14] lockd: Relocate nlmsvc_unlock API declarations Chuck Lever
2026-01-28 15:19 ` Chuck Lever [this message]
2026-01-28 15:19 ` [PATCH v4 07/14] lockd: Move xdr4.h from include/linux/lockd/ to fs/lockd/ Chuck Lever
2026-01-28 15:19 ` [PATCH v4 08/14] lockd: Move share.h " Chuck Lever
2026-01-28 15:19 ` [PATCH v4 09/14] lockd: Relocate include/linux/lockd/lockd.h Chuck Lever
2026-01-28 15:19 ` [PATCH v4 10/14] lockd: Remove lockd/debug.h Chuck Lever
2026-01-28 15:19 ` [PATCH v4 11/14] lockd: Move xdr.h from include/linux/lockd/ to fs/lockd/ Chuck Lever
2026-01-29 7:06 ` kernel test robot
2026-01-28 15:19 ` [PATCH v4 12/14] lockd: Make linux/lockd/nlm.h an internal header Chuck Lever
2026-01-28 15:19 ` [PATCH v4 13/14] lockd: Move nlm4svc_set_file_lock_range() Chuck Lever
2026-01-28 15:19 ` [PATCH v4 14/14] lockd: Relocate svc_version definitions to XDR layer Chuck Lever
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=20260128151935.1646063-7-cel@kernel.org \
--to=cel@kernel.org \
--cc=chuck.lever@oracle.com \
--cc=dai.ngo@oracle.com \
--cc=jlayton@kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=neilb@ownmail.net \
--cc=okorniev@redhat.com \
--cc=tom@talpey.com \
/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