From: Chuck Lever <cel@kernel.org>
To: NeilBrown <neil@brown.name>, 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, linux-fsdevel@vger.kernel.org,
Chuck Lever <chuck.lever@oracle.com>
Subject: [PATCH v5 3/7] NFSD: Add NFSD_CMD_UNLOCK_FILESYSTEM netlink command
Date: Thu, 26 Mar 2026 13:55:22 -0400 [thread overview]
Message-ID: <20260326-umount-kills-nfsv4-state-v5-3-d2ce071b3570@oracle.com> (raw)
In-Reply-To: <20260326-umount-kills-nfsv4-state-v5-0-d2ce071b3570@oracle.com>
From: Chuck Lever <chuck.lever@oracle.com>
Add NFSD_CMD_UNLOCK_FILESYSTEM as a dedicated netlink command for
revoking NFS state under a filesystem path, providing a netlink
equivalent of /proc/fs/nfsd/unlock_fs.
The command requires a "path" string attribute containing the
filesystem path whose state should be released. The handler
resolves the path to its superblock, then cancels async copies,
releases NLM locks, and revokes NFSv4 state on that superblock.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
Documentation/netlink/specs/nfsd.yaml | 16 ++++++++++++++
fs/nfsd/netlink.c | 12 +++++++++++
fs/nfsd/netlink.h | 1 +
fs/nfsd/nfsctl.c | 40 +++++++++++++++++++++++++++++++++++
include/uapi/linux/nfsd_netlink.h | 8 +++++++
5 files changed, 77 insertions(+)
diff --git a/Documentation/netlink/specs/nfsd.yaml b/Documentation/netlink/specs/nfsd.yaml
index 9918b9a84d88..e83209a4a19d 100644
--- a/Documentation/netlink/specs/nfsd.yaml
+++ b/Documentation/netlink/specs/nfsd.yaml
@@ -141,6 +141,13 @@ attribute-sets:
doc: struct sockaddr_in or struct sockaddr_in6.
checks:
min-len: 16
+ -
+ name: unlock-filesystem
+ attributes:
+ -
+ name: path
+ type: string
+ doc: Filesystem path whose state should be released.
operations:
list:
@@ -251,3 +258,12 @@ operations:
request:
attributes:
- address
+ -
+ name: unlock-filesystem
+ doc: revoke NFS state under a filesystem path
+ attribute-set: unlock-filesystem
+ flags: [admin-perm]
+ do:
+ request:
+ attributes:
+ - path
diff --git a/fs/nfsd/netlink.c b/fs/nfsd/netlink.c
index 6b7221ce6869..18afebaf4fef 100644
--- a/fs/nfsd/netlink.c
+++ b/fs/nfsd/netlink.c
@@ -53,6 +53,11 @@ static const struct nla_policy nfsd_unlock_ip_nl_policy[NFSD_A_UNLOCK_IP_ADDRESS
[NFSD_A_UNLOCK_IP_ADDRESS] = NLA_POLICY_MIN_LEN(16),
};
+/* NFSD_CMD_UNLOCK_FILESYSTEM - do */
+static const struct nla_policy nfsd_unlock_filesystem_nl_policy[NFSD_A_UNLOCK_FILESYSTEM_PATH + 1] = {
+ [NFSD_A_UNLOCK_FILESYSTEM_PATH] = { .type = NLA_NUL_STRING, },
+};
+
/* Ops table for nfsd */
static const struct genl_split_ops nfsd_nl_ops[] = {
{
@@ -115,6 +120,13 @@ static const struct genl_split_ops nfsd_nl_ops[] = {
.maxattr = NFSD_A_UNLOCK_IP_ADDRESS,
.flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
},
+ {
+ .cmd = NFSD_CMD_UNLOCK_FILESYSTEM,
+ .doit = nfsd_nl_unlock_filesystem_doit,
+ .policy = nfsd_unlock_filesystem_nl_policy,
+ .maxattr = NFSD_A_UNLOCK_FILESYSTEM_PATH,
+ .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
+ },
};
struct genl_family nfsd_nl_family __ro_after_init = {
diff --git a/fs/nfsd/netlink.h b/fs/nfsd/netlink.h
index 3c2d5996612f..9535782b529a 100644
--- a/fs/nfsd/netlink.h
+++ b/fs/nfsd/netlink.h
@@ -27,6 +27,7 @@ int nfsd_nl_listener_get_doit(struct sk_buff *skb, struct genl_info *info);
int nfsd_nl_pool_mode_set_doit(struct sk_buff *skb, struct genl_info *info);
int nfsd_nl_pool_mode_get_doit(struct sk_buff *skb, struct genl_info *info);
int nfsd_nl_unlock_ip_doit(struct sk_buff *skb, struct genl_info *info);
+int nfsd_nl_unlock_filesystem_doit(struct sk_buff *skb, struct genl_info *info);
extern struct genl_family nfsd_nl_family;
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index e1e89d52e6de..ed0d12f77405 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -2238,6 +2238,46 @@ int nfsd_nl_unlock_ip_doit(struct sk_buff *skb, struct genl_info *info)
return nlmsvc_unlock_all_by_ip(sap);
}
+/**
+ * nfsd_nl_unlock_filesystem_doit - revoke NFS state under a filesystem path
+ * @skb: reply buffer
+ * @info: netlink metadata and command arguments
+ *
+ * Return: 0 on success or a negative errno.
+ */
+int nfsd_nl_unlock_filesystem_doit(struct sk_buff *skb,
+ struct genl_info *info)
+{
+ struct net *net = genl_info_net(info);
+ struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+ struct path path;
+ int error;
+
+ if (GENL_REQ_ATTR_CHECK(info, NFSD_A_UNLOCK_FILESYSTEM_PATH))
+ return -EINVAL;
+
+ trace_nfsd_ctl_unlock_fs(net,
+ nla_data(info->attrs[NFSD_A_UNLOCK_FILESYSTEM_PATH]));
+ error = kern_path(
+ nla_data(info->attrs[NFSD_A_UNLOCK_FILESYSTEM_PATH]),
+ 0, &path);
+ if (error)
+ return error;
+
+ nfsd4_cancel_copy_by_sb(net, path.dentry->d_sb);
+ error = nlmsvc_unlock_all_by_sb(path.dentry->d_sb);
+
+ mutex_lock(&nfsd_mutex);
+ if (nn->nfsd_serv)
+ nfsd4_revoke_states(nn, path.dentry->d_sb);
+ else
+ error = -EINVAL;
+ mutex_unlock(&nfsd_mutex);
+
+ path_put(&path);
+ return error;
+}
+
/**
* nfsd_net_init - Prepare the nfsd_net portion of a new net namespace
* @net: a freshly-created network namespace
diff --git a/include/uapi/linux/nfsd_netlink.h b/include/uapi/linux/nfsd_netlink.h
index 4153e9c69fbf..51f926c0b15b 100644
--- a/include/uapi/linux/nfsd_netlink.h
+++ b/include/uapi/linux/nfsd_netlink.h
@@ -88,6 +88,13 @@ enum {
NFSD_A_UNLOCK_IP_MAX = (__NFSD_A_UNLOCK_IP_MAX - 1)
};
+enum {
+ NFSD_A_UNLOCK_FILESYSTEM_PATH = 1,
+
+ __NFSD_A_UNLOCK_FILESYSTEM_MAX,
+ NFSD_A_UNLOCK_FILESYSTEM_MAX = (__NFSD_A_UNLOCK_FILESYSTEM_MAX - 1)
+};
+
enum {
NFSD_CMD_RPC_STATUS_GET = 1,
NFSD_CMD_THREADS_SET,
@@ -99,6 +106,7 @@ enum {
NFSD_CMD_POOL_MODE_SET,
NFSD_CMD_POOL_MODE_GET,
NFSD_CMD_UNLOCK_IP,
+ NFSD_CMD_UNLOCK_FILESYSTEM,
__NFSD_CMD_MAX,
NFSD_CMD_MAX = (__NFSD_CMD_MAX - 1)
--
2.53.0
next prev parent reply other threads:[~2026-03-26 17:55 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-26 17:55 [PATCH v5 0/7] Automatic NFSv4 state revocation on filesystem unmount Chuck Lever
2026-03-26 17:55 ` [PATCH v5 1/7] NFSD: Extract revoke_one_stid() utility function Chuck Lever
2026-03-27 5:26 ` kernel test robot
2026-03-27 5:56 ` kernel test robot
2026-03-27 10:08 ` kernel test robot
2026-03-27 11:13 ` kernel test robot
2026-03-27 12:00 ` Jeff Layton
2026-03-27 12:21 ` Jeff Layton
2026-03-27 14:18 ` Chuck Lever
2026-03-26 17:55 ` [PATCH v5 2/7] NFSD: Add NFSD_CMD_UNLOCK_IP netlink command Chuck Lever
2026-03-27 12:06 ` Jeff Layton
2026-03-27 15:19 ` Chuck Lever
2026-03-27 15:52 ` Jeff Layton
2026-03-27 16:02 ` Chuck Lever
2026-03-26 17:55 ` Chuck Lever [this message]
2026-03-26 17:55 ` [PATCH v5 4/7] NFSD: Replace idr_for_each_entry_ul in find_one_sb_stid() Chuck Lever
2026-03-26 17:55 ` [PATCH v5 5/7] NFSD: Track svc_export in nfs4_stid Chuck Lever
2026-03-26 17:55 ` [PATCH v5 6/7] NFSD: Add NFSD_CMD_UNLOCK_EXPORT netlink command Chuck Lever
2026-03-26 17:55 ` [PATCH v5 7/7] NFSD: Close cached file handles when revoking export state Chuck Lever
2026-03-27 12:03 ` [PATCH v5 0/7] Automatic NFSv4 state revocation on filesystem unmount Jeff Layton
2026-03-27 13:29 ` Chuck Lever
2026-03-27 12:18 ` Jeff Layton
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=20260326-umount-kills-nfsv4-state-v5-3-d2ce071b3570@oracle.com \
--to=cel@kernel.org \
--cc=Dai.Ngo@oracle.com \
--cc=chuck.lever@oracle.com \
--cc=jlayton@kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=neil@brown.name \
--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;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).