Linux NFS development
 help / color / mirror / Atom feed
* [PATCH RFC] NFS: Add some knobs for disabling delegations in sysfs
@ 2025-11-25  0:15 Scott Mayhew
  2025-11-25  1:00 ` Trond Myklebust
  0 siblings, 1 reply; 7+ messages in thread
From: Scott Mayhew @ 2025-11-25  0:15 UTC (permalink / raw)
  To: trondmy, anna; +Cc: linux-nfs

There's occasionally a need to disable delegations, whether it be due to
known bugs or simply to give support staff some breathing room to
troubleshoot issues.  Currently the only real method for disabling
delegations in Linux NFS is via /proc/sys/fs/leases-enable, which has
some major drawbacks in that 1) it's only applicable to knfsd, and 2) it
affects all clients using that server.

Technically it's not really possible to disable delegations from the
client side since it's ultimately up to the server whether grants a
delegation or not, but we can achieve a similar affect in NFSv4.1+ by
manipulating the OPEN4_SHARE_ACCESS_WANT* flags.

Rather than proliferating a bunch of new mount options, add some sysfs
knobs to allow some of the nfs_server->caps flags related to delegations
to be adjusted.

Signed-off-by: Scott Mayhew <smayhew@redhat.com>
---
 fs/nfs/nfs4proc.c         |  8 ++++++
 fs/nfs/sysfs.c            | 55 +++++++++++++++++++++++++++++++++++++++
 include/linux/nfs_fs_sb.h |  1 +
 3 files changed, 64 insertions(+)

diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 93c6ce04332b..42810260f7d8 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1396,6 +1396,11 @@ nfs4_map_atomic_open_share(struct nfs_server *server,
 		res |= NFS4_SHARE_WANT_NO_DELEG;
 		goto out;
 	}
+	/* open delegation disabled in sysfs */
+	if (!(server->caps & NFS_CAP_DELEGATION)) {
+		res |= NFS4_SHARE_WANT_NO_DELEG;
+		goto out;
+	}
 	/* res |= NFS4_SHARE_WANT_NO_PREFERENCE; */
 	if (server->caps & NFS_CAP_DELEGTIME)
 		res |= NFS4_SHARE_WANT_DELEG_TIMESTAMPS;
@@ -10796,6 +10801,7 @@ static const struct nfs4_minor_version_ops nfs_v4_0_minor_ops = {
 	.minor_version = 0,
 	.init_caps = NFS_CAP_READDIRPLUS
 		| NFS_CAP_ATOMIC_OPEN
+		| NFS_CAP_DELEGATION
 		| NFS_CAP_POSIX_LOCK,
 	.init_client = nfs40_init_client,
 	.shutdown_client = nfs40_shutdown_client,
@@ -10822,6 +10828,7 @@ static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = {
 	.minor_version = 1,
 	.init_caps = NFS_CAP_READDIRPLUS
 		| NFS_CAP_ATOMIC_OPEN
+		| NFS_CAP_DELEGATION
 		| NFS_CAP_POSIX_LOCK
 		| NFS_CAP_STATEID_NFSV41
 		| NFS_CAP_ATOMIC_OPEN_V1
@@ -10848,6 +10855,7 @@ static const struct nfs4_minor_version_ops nfs_v4_2_minor_ops = {
 	.minor_version = 2,
 	.init_caps = NFS_CAP_READDIRPLUS
 		| NFS_CAP_ATOMIC_OPEN
+		| NFS_CAP_DELEGATION
 		| NFS_CAP_POSIX_LOCK
 		| NFS_CAP_STATEID_NFSV41
 		| NFS_CAP_ATOMIC_OPEN_V1
diff --git a/fs/nfs/sysfs.c b/fs/nfs/sysfs.c
index ea6e6168092b..cce2b7f594d5 100644
--- a/fs/nfs/sysfs.c
+++ b/fs/nfs/sysfs.c
@@ -323,6 +323,43 @@ implid_name_show(struct kobject *kobj, struct kobj_attribute *attr,
 
 static struct kobj_attribute nfs_sysfs_attr_implid_name = __ATTR_RO(implid_name);
 
+#define DEFINE_NFS_SYSFS_DELEG_KNOB(name, capname)			\
+	static ssize_t							\
+	name##_show(struct kobject *kobj, struct kobj_attribute *attr,	\
+					char *buf)			\
+	{								\
+		struct nfs_server *server = container_of(kobj, struct nfs_server, kobj); \
+		bool val = server->caps & NFS_CAP_##capname;		\
+									\
+		return sysfs_emit(buf, "%d\n", val);			\
+	}								\
+									\
+	static ssize_t							\
+	name##_store(struct kobject *kobj, struct kobj_attribute *attr,	\
+					const char *buf, size_t count)	\
+	{								\
+		struct nfs_server *server = container_of(kobj, struct nfs_server, kobj); \
+		bool val;						\
+		int ret;						\
+									\
+		ret = kstrtobool(buf, &val);				\
+		if (ret < 0)						\
+			return ret;					\
+									\
+		if (val == true)					\
+			server->caps |= NFS_CAP_##capname;		\
+		else							\
+			server->caps &= ~NFS_CAP_##capname;		\
+									\
+		return count;						\
+	}								\
+									\
+	static struct kobj_attribute nfs_sysfs_attr_##name = __ATTR_RW(name); \
+
+DEFINE_NFS_SYSFS_DELEG_KNOB(open_deleg, DELEGATION)
+DEFINE_NFS_SYSFS_DELEG_KNOB(open_xor_deleg, OPEN_XOR)
+DEFINE_NFS_SYSFS_DELEG_KNOB(timestamp_deleg, DELEGTIME)
+
 #endif /* IS_ENABLED(CONFIG_NFS_V4_1) */
 
 #define RPC_CLIENT_NAME_SIZE 64
@@ -381,6 +418,24 @@ static void nfs_sysfs_add_nfsv41_server(struct nfs_server *server)
 	if (ret < 0)
 		pr_warn("NFS: sysfs_create_file_ns for server-%d failed (%d)\n",
 			server->s_sysfs_id, ret);
+
+	ret = sysfs_create_file_ns(&server->kobj, &nfs_sysfs_attr_open_deleg.attr,
+				   nfs_netns_server_namespace(&server->kobj));
+	if (ret < 0)
+		pr_warn("NFS: sysfs_create_file_ns for server-%d failed (%d)\n",
+			server->s_sysfs_id, ret);
+
+	ret = sysfs_create_file_ns(&server->kobj, &nfs_sysfs_attr_open_xor_deleg.attr,
+				   nfs_netns_server_namespace(&server->kobj));
+	if (ret < 0)
+		pr_warn("NFS: sysfs_create_file_ns for server-%d failed (%d)\n",
+			server->s_sysfs_id, ret);
+
+	ret = sysfs_create_file_ns(&server->kobj, &nfs_sysfs_attr_timestamp_deleg.attr,
+				   nfs_netns_server_namespace(&server->kobj));
+	if (ret < 0)
+		pr_warn("NFS: sysfs_create_file_ns for server-%d failed (%d)\n",
+			server->s_sysfs_id, ret);
 }
 #else /* CONFIG_NFS_V4_1 */
 static inline void nfs_sysfs_add_nfsv41_server(struct nfs_server *server)
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index d30c0245031c..dcbb4ce6b3fd 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -305,6 +305,7 @@ struct nfs_server {
 #define NFS_CAP_REBOOT_LAYOUTRETURN	(1U << 8)
 #define NFS_CAP_OFFLOAD_STATUS	(1U << 9)
 #define NFS_CAP_ZERO_RANGE	(1U << 10)
+#define NFS_CAP_DELEGATION	(1U << 11)
 #define NFS_CAP_OPEN_XOR	(1U << 12)
 #define NFS_CAP_DELEGTIME	(1U << 13)
 #define NFS_CAP_POSIX_LOCK	(1U << 14)
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-01-27 16:04 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-25  0:15 [PATCH RFC] NFS: Add some knobs for disabling delegations in sysfs Scott Mayhew
2025-11-25  1:00 ` Trond Myklebust
2025-12-01 11:34   ` Scott Mayhew
2025-12-01 17:17     ` Trond Myklebust
2026-01-20 20:46   ` Olga Kornievskaia
2026-01-20 23:22     ` Trond Myklebust
2026-01-27 16:04       ` Jeff Layton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox