Linux NFS development
 help / color / mirror / Atom feed
* [PATCH 0/5] NFS: Client Side Directory Delegations
@ 2025-11-04 15:06 Anna Schumaker
  2025-11-04 15:06 ` [PATCH 1/5] NFS: Add support for sending GDD_GETATTR Anna Schumaker
                   ` (4 more replies)
  0 siblings, 5 replies; 11+ messages in thread
From: Anna Schumaker @ 2025-11-04 15:06 UTC (permalink / raw)
  To: linux-nfs, trond.myklebust; +Cc: anna

From: Anna Schumaker <anna.schumaker@oracle.com>

This patchset adds support for recallable directory delegations in the
NFS client, letting us shortcut some directory revalidation steps since
we know the directory hasn't changed from underneath us.

I tried to limit requesting a dir delegation to when we think the user
is doing work within a directory, so I look for ACCESS, CREATE, UNLINK,
and (same directory) RENAME calls. I'm open to suggestions for other
times I should be requesting a dir delegation too.

Finally, I add a new "directory_delegations" module parameter for
controlling the usage of directory delegations since they are still a
new feature. I (optimistically) have them enabled by default, and
setting this option to false will disable requesting delegations and
cause the client to return any existing delegations on the next use.

I'm happy to hear any suggestions for improvements!
Anna


Anna Schumaker (5):
  NFS: Add support for sending GDD_GETATTR
  NFS: Request a directory delegation on ACCESS, CREATE, and UNLINK
  NFS: Request a directory delegation during RENAME
  NFS: Shortcut lookup revalidations if we have a directory delegation
  NFS: Add a module option to disable directory delegations

 fs/nfs/delegation.c       |   8 +++
 fs/nfs/delegation.h       |  13 +++++
 fs/nfs/dir.c              |  19 +++++++
 fs/nfs/inode.c            |   3 ++
 fs/nfs/nfs3proc.c         |   3 +-
 fs/nfs/nfs4proc.c         |  62 ++++++++++++++++++++--
 fs/nfs/nfs4xdr.c          | 106 ++++++++++++++++++++++++++++++++++++++
 fs/nfs/proc.c             |   3 +-
 fs/nfs/unlink.c           |   3 +-
 include/linux/nfs_fs.h    |   1 +
 include/linux/nfs_fs_sb.h |   1 +
 include/linux/nfs_xdr.h   |  10 +++-
 12 files changed, 223 insertions(+), 9 deletions(-)

-- 
2.51.2


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

* [PATCH 1/5] NFS: Add support for sending GDD_GETATTR
  2025-11-04 15:06 [PATCH 0/5] NFS: Client Side Directory Delegations Anna Schumaker
@ 2025-11-04 15:06 ` Anna Schumaker
  2025-11-04 15:06 ` [PATCH 2/5] NFS: Request a directory delegation on ACCESS, CREATE, and UNLINK Anna Schumaker
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 11+ messages in thread
From: Anna Schumaker @ 2025-11-04 15:06 UTC (permalink / raw)
  To: linux-nfs, trond.myklebust; +Cc: anna

From: Anna Schumaker <anna.schumaker@oracle.com>

I add this to the existing GETATTR compound as an option extra step that
we can send if the "dir_deleg" flag is set to 'true'. Actually enabling
this value will happen in a later patch.

Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
---
 fs/nfs/nfs4xdr.c        | 106 ++++++++++++++++++++++++++++++++++++++++
 include/linux/nfs_xdr.h |   7 +++
 2 files changed, 113 insertions(+)

diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 1d0e6c10f921..b6fe30577fab 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -393,6 +393,20 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
 				XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5)
 #define encode_reclaim_complete_maxsz	(op_encode_hdr_maxsz + 4)
 #define decode_reclaim_complete_maxsz	(op_decode_hdr_maxsz + 4)
+#define encode_get_dir_deleg_maxsz (op_encode_hdr_maxsz + \
+				    4 /* gdda_signal_deleg_avail */ + \
+				    8 /* gdda_notification_types */ + \
+				    nfstime4_maxsz /* gdda_child_attr_delay */ + \
+				    nfstime4_maxsz /* gdda_dir_attr_delay */ + \
+				    nfs4_fattr_bitmap_maxsz /* gdda_child_attributes */ + \
+				    nfs4_fattr_bitmap_maxsz /* gdda_dir_attributes */)
+#define decode_get_dir_deleg_maxsz (op_decode_hdr_maxsz + \
+				    4 /* gddrnf_status */ + \
+				    encode_verifier_maxsz /* gddr_cookieverf */ + \
+				    encode_stateid_maxsz /* gddr_stateid */ + \
+				    8 /* gddr_notification */ + \
+				    nfs4_fattr_maxsz /* gddr_child_attributes */ + \
+				    nfs4_fattr_maxsz /* gddr_dir_attributes */)
 #define encode_getdeviceinfo_maxsz (op_encode_hdr_maxsz + \
 				XDR_QUADLEN(NFS4_DEVICEID4_SIZE) + \
 				1 /* layout type */ + \
@@ -444,6 +458,8 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
 #else /* CONFIG_NFS_V4_1 */
 #define encode_sequence_maxsz	0
 #define decode_sequence_maxsz	0
+#define encode_get_dir_deleg_maxsz 0
+#define decode_get_dir_deleg_maxsz 0
 #define encode_layoutreturn_maxsz 0
 #define decode_layoutreturn_maxsz 0
 #define encode_layoutget_maxsz	0
@@ -631,11 +647,13 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
 #define NFS4_enc_getattr_sz	(compound_encode_hdr_maxsz + \
 				encode_sequence_maxsz + \
 				encode_putfh_maxsz + \
+				encode_get_dir_deleg_maxsz + \
 				encode_getattr_maxsz + \
 				encode_renew_maxsz)
 #define NFS4_dec_getattr_sz	(compound_decode_hdr_maxsz + \
 				decode_sequence_maxsz + \
 				decode_putfh_maxsz + \
+				decode_get_dir_deleg_maxsz + \
 				decode_getattr_maxsz + \
 				decode_renew_maxsz)
 #define NFS4_enc_lookup_sz	(compound_encode_hdr_maxsz + \
@@ -2007,6 +2025,33 @@ static void encode_sequence(struct xdr_stream *xdr,
 }
 
 #ifdef CONFIG_NFS_V4_1
+static void
+encode_get_dir_delegation(struct xdr_stream *xdr, struct compound_hdr *hdr)
+{
+	struct timespec64 ts = { 0, 0 };
+	u32 notifications[1] = { 0 };
+	u32 attributes[1] = { 0 };
+	__be32 *p;
+
+	encode_op_hdr(xdr, OP_GET_DIR_DELEGATION, decode_get_dir_deleg_maxsz, hdr);
+
+	/* We don't handle CB_RECALLABLE_OBJ_AVAIL yet. */
+	xdr_stream_encode_bool(xdr, false);
+
+	xdr_encode_bitmap4(xdr, notifications, ARRAY_SIZE(notifications));
+
+	/* Request no delay on attribute updates */
+	p = reserve_space(xdr, 12 + 12);
+	p = xdr_encode_nfstime4(p, &ts);
+	xdr_encode_nfstime4(p, &ts);
+
+	/* Requested child attributes */
+	xdr_encode_bitmap4(xdr, attributes, ARRAY_SIZE(attributes));
+
+	/* Requested dir attributes */
+	xdr_encode_bitmap4(xdr, attributes, ARRAY_SIZE(attributes));
+}
+
 static void
 encode_getdeviceinfo(struct xdr_stream *xdr,
 		     const struct nfs4_getdeviceinfo_args *args,
@@ -2142,6 +2187,11 @@ static void encode_free_stateid(struct xdr_stream *xdr,
 	encode_nfs4_stateid(xdr, &args->stateid);
 }
 #else
+static inline void
+encode_get_dir_delegation(struct xdr_stream *xdr, struct compound_hdr *hdr)
+{
+}
+
 static inline void
 encode_layoutreturn(struct xdr_stream *xdr,
 		    const struct nfs4_layoutreturn_args *args,
@@ -2356,6 +2406,8 @@ static void nfs4_xdr_enc_getattr(struct rpc_rqst *req, struct xdr_stream *xdr,
 	encode_compound_hdr(xdr, req, &hdr);
 	encode_sequence(xdr, &args->seq_args, &hdr);
 	encode_putfh(xdr, args->fh, &hdr);
+	if (args->get_dir_deleg)
+		encode_get_dir_delegation(xdr, &hdr);
 	encode_getfattr(xdr, args->bitmask, &hdr);
 	encode_nops(&hdr);
 }
@@ -5994,6 +6046,49 @@ static int decode_layout_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
 	return decode_stateid(xdr, stateid);
 }
 
+static int decode_get_dir_delegation(struct xdr_stream *xdr,
+				     struct nfs4_getattr_res *res)
+{
+	struct nfs4_gdd_res *gdd_res = res->gdd_res;
+	nfs4_verifier cookieverf;
+	u32 bitmap[1];
+	int status;
+
+	status = decode_op_hdr(xdr, OP_GET_DIR_DELEGATION);
+	if (status)
+		return status;
+
+	if (xdr_stream_decode_u32(xdr, &gdd_res->status))
+		return -EIO;
+
+	if (gdd_res->status == GDD4_UNAVAIL)
+		return xdr_inline_decode(xdr, 4) ? 0 : -EIO;
+
+	status = decode_verifier(xdr, &cookieverf);
+	if (status)
+		return status;
+
+	status = decode_delegation_stateid(xdr, &gdd_res->deleg);
+	if (status)
+		return status;
+
+	/* Decode supported notification types. */
+	status = decode_bitmap4(xdr, bitmap, ARRAY_SIZE(bitmap));
+	if (status < 0)
+		return status;
+
+	/* Decode supported child attributes. */
+	status = decode_bitmap4(xdr, bitmap, ARRAY_SIZE(bitmap));
+	if (status < 0)
+		return status;
+
+	/* Decode supported attributes. */
+	status = decode_bitmap4(xdr, bitmap, ARRAY_SIZE(bitmap));
+	if (status < 0)
+		return status;
+	return 0;
+}
+
 static int decode_getdeviceinfo(struct xdr_stream *xdr,
 				struct nfs4_getdeviceinfo_res *res)
 {
@@ -6208,6 +6303,12 @@ static int decode_free_stateid(struct xdr_stream *xdr,
 	return res->status;
 }
 #else
+static int decode_get_dir_delegation(struct xdr_stream *xdr,
+				     struct nfs4_getattr_res *res)
+{
+	return 0;
+}
+
 static inline
 int decode_layoutreturn(struct xdr_stream *xdr,
 			       struct nfs4_layoutreturn_res *res)
@@ -6525,6 +6626,11 @@ static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
 	status = decode_putfh(xdr);
 	if (status)
 		goto out;
+	if (res->gdd_res) {
+		status = decode_get_dir_delegation(xdr, res);
+		if (status)
+			goto out;
+	}
 	status = decode_getfattr(xdr, res->fattr, res->server);
 out:
 	return status;
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 31463286402f..8bf6cba96c46 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1092,12 +1092,19 @@ struct nfs4_getattr_arg {
 	struct nfs4_sequence_args	seq_args;
 	const struct nfs_fh *		fh;
 	const u32 *			bitmask;
+	bool				get_dir_deleg;
+};
+
+struct nfs4_gdd_res {
+	u32				status;
+	nfs4_stateid			deleg;
 };
 
 struct nfs4_getattr_res {
 	struct nfs4_sequence_res	seq_res;
 	const struct nfs_server *	server;
 	struct nfs_fattr *		fattr;
+	struct nfs4_gdd_res *		gdd_res;
 };
 
 struct nfs4_link_arg {
-- 
2.51.2


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

* [PATCH 2/5] NFS: Request a directory delegation on ACCESS, CREATE, and UNLINK
  2025-11-04 15:06 [PATCH 0/5] NFS: Client Side Directory Delegations Anna Schumaker
  2025-11-04 15:06 ` [PATCH 1/5] NFS: Add support for sending GDD_GETATTR Anna Schumaker
@ 2025-11-04 15:06 ` Anna Schumaker
  2025-12-02 16:01   ` Jon Hunter
  2025-11-04 15:06 ` [PATCH 3/5] NFS: Request a directory delegation during RENAME Anna Schumaker
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 11+ messages in thread
From: Anna Schumaker @ 2025-11-04 15:06 UTC (permalink / raw)
  To: linux-nfs, trond.myklebust; +Cc: anna

From: Anna Schumaker <anna.schumaker@oracle.com>

This patch adds a new flag: NFS_INO_REQ_DIR_DELEG to signal that a
directory wants to request a directory delegation the next time it does
a GETATTR. I have the client request a directory delegation when doing
an access, create, or unlink call since these calls indicate that a user
is working with a directory.

Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
---
 fs/nfs/delegation.c       |  1 +
 fs/nfs/delegation.h       |  6 +++++
 fs/nfs/nfs4proc.c         | 55 ++++++++++++++++++++++++++++++++++++---
 include/linux/nfs_fs.h    |  1 +
 include/linux/nfs_fs_sb.h |  1 +
 5 files changed, 60 insertions(+), 4 deletions(-)

diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 9d3a5f29f17f..b4c192f00e94 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -379,6 +379,7 @@ nfs_detach_delegation_locked(struct nfs_inode *nfsi,
 	delegation->inode = NULL;
 	rcu_assign_pointer(nfsi->delegation, NULL);
 	spin_unlock(&delegation->lock);
+	clear_bit(NFS_INO_REQ_DIR_DELEG, &nfsi->flags);
 	return delegation;
 }
 
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h
index 08ec2e9c68a4..def50e8a83bf 100644
--- a/fs/nfs/delegation.h
+++ b/fs/nfs/delegation.h
@@ -124,6 +124,12 @@ static inline int nfs_have_delegated_mtime(struct inode *inode)
 						 NFS_DELEGATION_FLAG_TIME);
 }
 
+static inline void nfs_request_directory_delegation(struct inode *inode)
+{
+	if (S_ISDIR(inode->i_mode))
+		set_bit(NFS_INO_REQ_DIR_DELEG, &NFS_I(inode)->flags);
+}
+
 int nfs4_delegation_hash_alloc(struct nfs_server *server);
 
 #endif
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 411776718494..bd718a270e72 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4460,6 +4460,28 @@ static int nfs4_get_referral(struct rpc_clnt *client, struct inode *dir,
 	return status;
 }
 
+#if IS_ENABLED(CONFIG_NFS_V4_1)
+static bool should_request_dir_deleg(struct inode *inode)
+{
+	if (!inode)
+		return false;
+	if (!S_ISDIR(inode->i_mode))
+		return false;
+	if (!nfs_server_capable(inode, NFS_CAP_DIR_DELEG))
+		return false;
+	if (!test_and_clear_bit(NFS_INO_REQ_DIR_DELEG, &(NFS_I(inode)->flags)))
+		return false;
+	if (nfs4_have_delegation(inode, FMODE_READ, 0))
+		return false;
+	return true;
+}
+#else
+static bool should_request_dir_deleg(struct inode *inode)
+{
+	return false;
+}
+#endif /* CONFIG_NFS_V4_1 */
+
 static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
 				struct nfs_fattr *fattr, struct inode *inode)
 {
@@ -4477,7 +4499,9 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
 		.rpc_argp = &args,
 		.rpc_resp = &res,
 	};
+	struct nfs4_gdd_res gdd_res;
 	unsigned short task_flags = 0;
+	int status;
 
 	if (nfs4_has_session(server->nfs_client))
 		task_flags = RPC_TASK_MOVEABLE;
@@ -4486,11 +4510,26 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
 	if (inode && (server->flags & NFS_MOUNT_SOFTREVAL))
 		task_flags |= RPC_TASK_TIMEOUT;
 
+	args.get_dir_deleg = should_request_dir_deleg(inode);
+	if (args.get_dir_deleg)
+		res.gdd_res = &gdd_res;
+
 	nfs4_bitmap_copy_adjust(bitmask, nfs4_bitmask(server, fattr->label), inode, 0);
 	nfs_fattr_init(fattr);
 	nfs4_init_sequence(&args.seq_args, &res.seq_res, 0, 0);
-	return nfs4_do_call_sync(server->client, server, &msg,
-			&args.seq_args, &res.seq_res, task_flags);
+
+	status = nfs4_do_call_sync(server->client, server, &msg,
+				   &args.seq_args, &res.seq_res, task_flags);
+	if (args.get_dir_deleg) {
+		if (status == -EOPNOTSUPP) {
+			server->caps &= ~NFS_CAP_DIR_DELEG;
+		} else if (status == 0 && gdd_res.status == GDD4_OK) {
+			status = nfs_inode_set_delegation(inode, current_cred(),
+							  FMODE_READ, &gdd_res.deleg,
+							  0, NFS4_OPEN_DELEGATE_READ);
+		}
+	}
+	return status;
 }
 
 int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
@@ -4503,8 +4542,10 @@ int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
 	do {
 		err = _nfs4_proc_getattr(server, fhandle, fattr, inode);
 		trace_nfs4_getattr(server, fhandle, fattr, err);
-		err = nfs4_handle_exception(server, err,
-				&exception);
+		if (err == -EOPNOTSUPP)
+			exception.retry = true;
+		else
+			err = nfs4_handle_exception(server, err, &exception);
 	} while (exception.retry);
 	return err;
 }
@@ -4765,6 +4806,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
 	int status = 0;
 
 	if (!nfs4_have_delegation(inode, FMODE_READ, 0)) {
+		nfs_request_directory_delegation(inode);
 		res.fattr = nfs_alloc_fattr();
 		if (res.fattr == NULL)
 			return -ENOMEM;
@@ -4872,6 +4914,8 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
 
 	ilabel = nfs4_label_init_security(dir, dentry, sattr, &l);
 
+	nfs_request_directory_delegation(dir);
+
 	if (!(server->attr_bitmask[2] & FATTR4_WORD2_MODE_UMASK))
 		sattr->ia_mode &= ~current_umask();
 	state = nfs4_do_open(dir, ctx, flags, sattr, ilabel, NULL);
@@ -4968,6 +5012,7 @@ static void nfs4_proc_unlink_setup(struct rpc_message *msg,
 	nfs4_init_sequence(&args->seq_args, &res->seq_res, 1, 0);
 
 	nfs_fattr_init(res->dir_attr);
+	nfs_request_directory_delegation(d_inode(dentry->d_parent));
 
 	if (inode) {
 		nfs4_inode_return_delegation(inode);
@@ -10819,6 +10864,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_DIR_DELEG
 		| NFS_CAP_POSIX_LOCK
 		| NFS_CAP_STATEID_NFSV41
 		| NFS_CAP_ATOMIC_OPEN_V1
@@ -10845,6 +10891,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_DIR_DELEG
 		| NFS_CAP_POSIX_LOCK
 		| NFS_CAP_STATEID_NFSV41
 		| NFS_CAP_ATOMIC_OPEN_V1
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index c585939b6cd6..a6624edb7226 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -344,6 +344,7 @@ struct nfs4_copy_state {
 #define NFS_INO_LAYOUTCOMMITTING (10)		/* layoutcommit inflight */
 #define NFS_INO_LAYOUTSTATS	(11)		/* layoutstats inflight */
 #define NFS_INO_ODIRECT		(12)		/* I/O setting is O_DIRECT */
+#define NFS_INO_REQ_DIR_DELEG	(13)		/* Request a directory delegation */
 
 static inline struct nfs_inode *NFS_I(const struct inode *inode)
 {
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index d30c0245031c..4ba04de6b1ca 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_DIR_DELEG	(1U << 11)
 #define NFS_CAP_OPEN_XOR	(1U << 12)
 #define NFS_CAP_DELEGTIME	(1U << 13)
 #define NFS_CAP_POSIX_LOCK	(1U << 14)
-- 
2.51.2


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

* [PATCH 3/5] NFS: Request a directory delegation during RENAME
  2025-11-04 15:06 [PATCH 0/5] NFS: Client Side Directory Delegations Anna Schumaker
  2025-11-04 15:06 ` [PATCH 1/5] NFS: Add support for sending GDD_GETATTR Anna Schumaker
  2025-11-04 15:06 ` [PATCH 2/5] NFS: Request a directory delegation on ACCESS, CREATE, and UNLINK Anna Schumaker
@ 2025-11-04 15:06 ` Anna Schumaker
  2025-11-04 15:06 ` [PATCH 4/5] NFS: Shortcut lookup revalidations if we have a directory delegation Anna Schumaker
  2025-11-04 15:06 ` [PATCH 5/5] NFS: Add a module option to disable directory delegations Anna Schumaker
  4 siblings, 0 replies; 11+ messages in thread
From: Anna Schumaker @ 2025-11-04 15:06 UTC (permalink / raw)
  To: linux-nfs, trond.myklebust; +Cc: anna

From: Anna Schumaker <anna.schumaker@oracle.com>

If we notice that we're renaming a file within a directory then we take
that as a sign that the user is working with the current directory and
may want a delegation to avoid extra revalidations when possible.

The nfs_request_directory_delegation() function exists within the NFS v4
module, so I add an extra flag to rename_setup() to indicate if a dentry
is being renamed within the same parent directory.

Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
---
 fs/nfs/nfs3proc.c       | 3 ++-
 fs/nfs/nfs4proc.c       | 5 ++++-
 fs/nfs/proc.c           | 3 ++-
 fs/nfs/unlink.c         | 3 ++-
 include/linux/nfs_xdr.h | 3 ++-
 5 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index a4cb67573aa7..1181f9cc6dbd 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -483,7 +483,8 @@ nfs3_proc_unlink_done(struct rpc_task *task, struct inode *dir)
 static void
 nfs3_proc_rename_setup(struct rpc_message *msg,
 		struct dentry *old_dentry,
-		struct dentry *new_dentry)
+		struct dentry *new_dentry,
+		struct inode *same_parent)
 {
 	msg->rpc_proc = &nfs3_procedures[NFS3PROC_RENAME];
 }
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index bd718a270e72..fa176db362c7 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -5047,7 +5047,8 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
 
 static void nfs4_proc_rename_setup(struct rpc_message *msg,
 		struct dentry *old_dentry,
-		struct dentry *new_dentry)
+		struct dentry *new_dentry,
+		struct inode *same_parent)
 {
 	struct nfs_renameargs *arg = msg->rpc_argp;
 	struct nfs_renameres *res = msg->rpc_resp;
@@ -5058,6 +5059,8 @@ static void nfs4_proc_rename_setup(struct rpc_message *msg,
 		nfs4_inode_make_writeable(old_inode);
 	if (new_inode)
 		nfs4_inode_return_delegation(new_inode);
+	if (same_parent)
+		nfs_request_directory_delegation(same_parent);
 	msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME];
 	res->server = NFS_SB(old_dentry->d_sb);
 	nfs4_init_sequence(&arg->seq_args, &res->seq_res, 1, 0);
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 63e71310b9f6..39df80e4ae6f 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -353,7 +353,8 @@ static int nfs_proc_unlink_done(struct rpc_task *task, struct inode *dir)
 static void
 nfs_proc_rename_setup(struct rpc_message *msg,
 		struct dentry *old_dentry,
-		struct dentry *new_dentry)
+		struct dentry *new_dentry,
+		struct inode *same_parent)
 {
 	msg->rpc_proc = &nfs_procedures[NFSPROC_RENAME];
 }
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index b55467911648..4db818c0f9dd 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -390,7 +390,8 @@ nfs_async_rename(struct inode *old_dir, struct inode *new_dir,
 
 	nfs_sb_active(old_dir->i_sb);
 
-	NFS_PROTO(data->old_dir)->rename_setup(&msg, old_dentry, new_dentry);
+	NFS_PROTO(data->old_dir)->rename_setup(&msg, old_dentry, new_dentry,
+					old_dir == new_dir ? old_dir : NULL);
 
 	return rpc_run_task(&task_setup_data);
 }
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 8bf6cba96c46..79fe2dfb470f 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1808,7 +1808,8 @@ struct nfs_rpc_ops {
 	int	(*unlink_done) (struct rpc_task *, struct inode *);
 	void	(*rename_setup)  (struct rpc_message *msg,
 			struct dentry *old_dentry,
-			struct dentry *new_dentry);
+			struct dentry *new_dentry,
+			struct inode *same_parent);
 	void	(*rename_rpc_prepare)(struct rpc_task *task, struct nfs_renamedata *);
 	int	(*rename_done) (struct rpc_task *task, struct inode *old_dir, struct inode *new_dir);
 	int	(*link)    (struct inode *, struct inode *, const struct qstr *);
-- 
2.51.2


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

* [PATCH 4/5] NFS: Shortcut lookup revalidations if we have a directory delegation
  2025-11-04 15:06 [PATCH 0/5] NFS: Client Side Directory Delegations Anna Schumaker
                   ` (2 preceding siblings ...)
  2025-11-04 15:06 ` [PATCH 3/5] NFS: Request a directory delegation during RENAME Anna Schumaker
@ 2025-11-04 15:06 ` Anna Schumaker
  2025-11-04 15:06 ` [PATCH 5/5] NFS: Add a module option to disable directory delegations Anna Schumaker
  4 siblings, 0 replies; 11+ messages in thread
From: Anna Schumaker @ 2025-11-04 15:06 UTC (permalink / raw)
  To: linux-nfs, trond.myklebust; +Cc: anna

From: Anna Schumaker <anna.schumaker@oracle.com>

Holding a directory delegation means we know that nobody else has
modified the directory on the server, so we can take a few revalidation
shortcuts.

Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
---
 fs/nfs/delegation.h |  5 +++++
 fs/nfs/dir.c        | 19 +++++++++++++++++++
 fs/nfs/inode.c      |  3 +++
 3 files changed, 27 insertions(+)

diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h
index def50e8a83bf..8968f62bf438 100644
--- a/fs/nfs/delegation.h
+++ b/fs/nfs/delegation.h
@@ -130,6 +130,11 @@ static inline void nfs_request_directory_delegation(struct inode *inode)
 		set_bit(NFS_INO_REQ_DIR_DELEG, &NFS_I(inode)->flags);
 }
 
+static inline bool nfs_have_directory_delegation(struct inode *inode)
+{
+	return S_ISDIR(inode->i_mode) && nfs_have_delegated_attributes(inode);
+}
+
 int nfs4_delegation_hash_alloc(struct nfs_server *server);
 
 #endif
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index ea9f6ca8f30f..2cc784ae0581 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1514,6 +1514,15 @@ static int nfs_check_verifier(struct inode *dir, struct dentry *dentry,
 		return 0;
 	if (!nfs_dentry_verify_change(dir, dentry))
 		return 0;
+
+	/*
+	 * If we have a directory delegation then we don't need to revalidate
+	 * the directory. The delegation will either get recalled or we will
+	 * receive a notification when it changes.
+	 */
+	if (nfs_have_directory_delegation(dir))
+		return 0;
+
 	/* Revalidate nfsi->cache_change_attribute before we declare a match */
 	if (nfs_mapping_need_revalidate_inode(dir)) {
 		if (rcu_walk)
@@ -2202,6 +2211,13 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
 }
 EXPORT_SYMBOL_GPL(nfs_atomic_open);
 
+static int
+nfs_lookup_revalidate_delegated_parent(struct inode *dir, struct dentry *dentry,
+				       struct inode *inode)
+{
+	return nfs_lookup_revalidate_done(dir, dentry, inode, 1);
+}
+
 static int
 nfs4_lookup_revalidate(struct inode *dir, const struct qstr *name,
 		       struct dentry *dentry, unsigned int flags)
@@ -2229,6 +2245,9 @@ nfs4_lookup_revalidate(struct inode *dir, const struct qstr *name,
 	if (nfs_verifier_is_delegated(dentry))
 		return nfs_lookup_revalidate_delegated(dir, dentry, inode);
 
+	if (nfs_have_directory_delegation(dir))
+		return nfs_lookup_revalidate_delegated_parent(dir, dentry, inode);
+
 	/* NFS only supports OPEN on regular files */
 	if (!S_ISREG(inode->i_mode))
 		goto full_reval;
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 18b57c7c2f97..6c92211835e7 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1383,6 +1383,9 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
 		status = pnfs_sync_inode(inode, false);
 		if (status)
 			goto out;
+	} else if (nfs_have_directory_delegation(inode)) {
+		status = 0;
+		goto out;
 	}
 
 	status = -ENOMEM;
-- 
2.51.2


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

* [PATCH 5/5] NFS: Add a module option to disable directory delegations
  2025-11-04 15:06 [PATCH 0/5] NFS: Client Side Directory Delegations Anna Schumaker
                   ` (3 preceding siblings ...)
  2025-11-04 15:06 ` [PATCH 4/5] NFS: Shortcut lookup revalidations if we have a directory delegation Anna Schumaker
@ 2025-11-04 15:06 ` Anna Schumaker
  4 siblings, 0 replies; 11+ messages in thread
From: Anna Schumaker @ 2025-11-04 15:06 UTC (permalink / raw)
  To: linux-nfs, trond.myklebust; +Cc: anna

From: Anna Schumaker <anna.schumaker@oracle.com>

When this option is disabled then the client will not request directory
delegations or check if we have one during the revalidation paths.

Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
---
 fs/nfs/delegation.c | 7 +++++++
 fs/nfs/delegation.h | 2 ++
 fs/nfs/nfs4proc.c   | 2 ++
 3 files changed, 11 insertions(+)

diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index b4c192f00e94..2248e3ad089a 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -30,6 +30,11 @@
 static unsigned nfs_delegation_watermark = NFS_DEFAULT_DELEGATION_WATERMARK;
 module_param_named(delegation_watermark, nfs_delegation_watermark, uint, 0644);
 
+bool directory_delegations = true;
+module_param(directory_delegations, bool, 0644);
+MODULE_PARM_DESC(directory_delegations,
+		 "Enable the use of directory delegations, defaults to on.");
+
 static struct hlist_head *nfs_delegation_hash(struct nfs_server *server,
 		const struct nfs_fh *fhandle)
 {
@@ -143,6 +148,8 @@ static int nfs4_do_check_delegation(struct inode *inode, fmode_t type,
  */
 int nfs4_have_delegation(struct inode *inode, fmode_t type, int flags)
 {
+	if (S_ISDIR(inode->i_mode) && !directory_delegations)
+		nfs_inode_evict_delegation(inode);
 	return nfs4_do_check_delegation(inode, type, flags, true);
 }
 
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h
index 8968f62bf438..46d866adb5c2 100644
--- a/fs/nfs/delegation.h
+++ b/fs/nfs/delegation.h
@@ -124,6 +124,8 @@ static inline int nfs_have_delegated_mtime(struct inode *inode)
 						 NFS_DELEGATION_FLAG_TIME);
 }
 
+extern bool directory_delegations;
+
 static inline void nfs_request_directory_delegation(struct inode *inode)
 {
 	if (S_ISDIR(inode->i_mode))
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index fa176db362c7..33b64d000c40 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4463,6 +4463,8 @@ static int nfs4_get_referral(struct rpc_clnt *client, struct inode *dir,
 #if IS_ENABLED(CONFIG_NFS_V4_1)
 static bool should_request_dir_deleg(struct inode *inode)
 {
+	if (!directory_delegations)
+		return false;
 	if (!inode)
 		return false;
 	if (!S_ISDIR(inode->i_mode))
-- 
2.51.2


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

* Re: [PATCH 2/5] NFS: Request a directory delegation on ACCESS, CREATE, and UNLINK
  2025-11-04 15:06 ` [PATCH 2/5] NFS: Request a directory delegation on ACCESS, CREATE, and UNLINK Anna Schumaker
@ 2025-12-02 16:01   ` Jon Hunter
  2025-12-03 15:56     ` Jon Hunter
  0 siblings, 1 reply; 11+ messages in thread
From: Jon Hunter @ 2025-12-02 16:01 UTC (permalink / raw)
  To: Anna Schumaker, linux-nfs, trond.myklebust; +Cc: linux-tegra@vger.kernel.org

Hi Anna,

On 04/11/2025 15:06, Anna Schumaker wrote:
> From: Anna Schumaker <anna.schumaker@oracle.com>
> 
> This patch adds a new flag: NFS_INO_REQ_DIR_DELEG to signal that a
> directory wants to request a directory delegation the next time it does
> a GETATTR. I have the client request a directory delegation when doing
> an access, create, or unlink call since these calls indicate that a user
> is working with a directory.
> 
> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>


We use NFS for boot testing our boards and once this commit landed in 
-next a lot of them, but no all, started failing to boot. Bisect is 
pointing to this change.

We have a custom init script that runs to mount the rootfs and I see 
that it displays ...

[   10.238091] Run /init as init process
[   10.266026] ERROR: mounting debugfs fail...
[   10.286535] Root device found: nfs
[   10.300342] Ethernet interface: eth0
[   10.313920] IP Address: 192.168.99.2
[   10.382738] Rootfs mounted over nfs
[   10.416010] Switching from initrd to actual rootfs

Its odd it fails to mount the debugfs. There are no particular errors 
that are shown but it never boots up completely. I am unable to cleanly 
revert this due to other dependencies, but if you have any suggestions 
for me to try, please let me know.

Jon

-- 
nvpublic


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

* Re: [PATCH 2/5] NFS: Request a directory delegation on ACCESS, CREATE, and UNLINK
  2025-12-02 16:01   ` Jon Hunter
@ 2025-12-03 15:56     ` Jon Hunter
  2025-12-03 16:23       ` Trond Myklebust
  0 siblings, 1 reply; 11+ messages in thread
From: Jon Hunter @ 2025-12-03 15:56 UTC (permalink / raw)
  To: Anna Schumaker, linux-nfs, trond.myklebust; +Cc: linux-tegra@vger.kernel.org


On 02/12/2025 16:01, Jon Hunter wrote:
> Hi Anna,
> 
> On 04/11/2025 15:06, Anna Schumaker wrote:
>> From: Anna Schumaker <anna.schumaker@oracle.com>
>>
>> This patch adds a new flag: NFS_INO_REQ_DIR_DELEG to signal that a
>> directory wants to request a directory delegation the next time it does
>> a GETATTR. I have the client request a directory delegation when doing
>> an access, create, or unlink call since these calls indicate that a user
>> is working with a directory.
>>
>> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
> 
> 
> We use NFS for boot testing our boards and once this commit landed in - 
> next a lot of them, but no all, started failing to boot. Bisect is 
> pointing to this change.
> 
> We have a custom init script that runs to mount the rootfs and I see 
> that it displays ...
> 
> [   10.238091] Run /init as init process
> [   10.266026] ERROR: mounting debugfs fail...
> [   10.286535] Root device found: nfs
> [   10.300342] Ethernet interface: eth0
> [   10.313920] IP Address: 192.168.99.2
> [   10.382738] Rootfs mounted over nfs
> [   10.416010] Switching from initrd to actual rootfs

It appears that there are multiple boot issues on -next at the moment
and the above it not the relevant part for this particular issue.
Looking further at the logs I am seeing the following errors which
are related to this change ...

[   11.100334] systemd[1]: Failed to open directory /etc/systemd/system, ignoring: Unknown error 524
[   11.119234] systemd[1]: Failed to open directory /lib/systemd/system, ignoring: Unknown error 524
[   11.143487] systemd[1]: Failed to load default target: No such file or directory
[   11.158620] systemd[1]: Trying to load rescue target...
[   11.169388] systemd[1]: Failed to load rescue target: No such file or directory
[   11.188856] systemd[1]: Freezing execution.

Thanks
Jon

-- 
nvpublic


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

* Re: [PATCH 2/5] NFS: Request a directory delegation on ACCESS, CREATE, and UNLINK
  2025-12-03 15:56     ` Jon Hunter
@ 2025-12-03 16:23       ` Trond Myklebust
  2025-12-03 21:06         ` Jon Hunter
  0 siblings, 1 reply; 11+ messages in thread
From: Trond Myklebust @ 2025-12-03 16:23 UTC (permalink / raw)
  To: Jon Hunter, Anna Schumaker, linux-nfs; +Cc: linux-tegra@vger.kernel.org

Hi Jon,

On Wed, 2025-12-03 at 15:56 +0000, Jon Hunter wrote:
> 
> On 02/12/2025 16:01, Jon Hunter wrote:
> > Hi Anna,
> > 
> > On 04/11/2025 15:06, Anna Schumaker wrote:
> > > From: Anna Schumaker <anna.schumaker@oracle.com>
> > > 
> > > This patch adds a new flag: NFS_INO_REQ_DIR_DELEG to signal that
> > > a
> > > directory wants to request a directory delegation the next time
> > > it does
> > > a GETATTR. I have the client request a directory delegation when
> > > doing
> > > an access, create, or unlink call since these calls indicate that
> > > a user
> > > is working with a directory.
> > > 
> > > Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
> > 
> > 
> > We use NFS for boot testing our boards and once this commit landed
> > in - 
> > next a lot of them, but no all, started failing to boot. Bisect is 
> > pointing to this change.
> > 
> > We have a custom init script that runs to mount the rootfs and I
> > see 
> > that it displays ...
> > 
> > [   10.238091] Run /init as init process
> > [   10.266026] ERROR: mounting debugfs fail...
> > [   10.286535] Root device found: nfs
> > [   10.300342] Ethernet interface: eth0
> > [   10.313920] IP Address: 192.168.99.2
> > [   10.382738] Rootfs mounted over nfs
> > [   10.416010] Switching from initrd to actual rootfs
> 
> It appears that there are multiple boot issues on -next at the moment
> and the above it not the relevant part for this particular issue.
> Looking further at the logs I am seeing the following errors which
> are related to this change ...
> 
> [   11.100334] systemd[1]: Failed to open directory
> /etc/systemd/system, ignoring: Unknown error 524
> [   11.119234] systemd[1]: Failed to open directory
> /lib/systemd/system, ignoring: Unknown error 524
> [   11.143487] systemd[1]: Failed to load default target: No such
> file or directory
> [   11.158620] systemd[1]: Trying to load rescue target...
> [   11.169388] systemd[1]: Failed to load rescue target: No such file
> or directory
> [   11.188856] systemd[1]: Freezing execution.
> 
> Thanks
> Jon

Does the following patch fix it for you?

8<---------------------------------------------
From 849bdbd3a2136a86c809ce6a7fa6ae30e9f0728a Mon Sep 17 00:00:00 2001
Message-ID: <849bdbd3a2136a86c809ce6a7fa6ae30e9f0728a.1764778907.git.trond.myklebust@hammerspace.com>
From: Trond Myklebust <trond.myklebust@hammerspace.com>
Date: Wed, 3 Dec 2025 11:17:25 -0500
Subject: [PATCH] NFSv4: Handle NFS4ERR_NOTSUPP errors for directory
 delegations

The error NFS4ERR_NOTSUPP will be returned for operations that are
legal, but not supported by the server.

Fixes: 156b09482933 ("NFS: Request a directory delegation on ACCESS, CREATE, and UNLINK")
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
---
 fs/nfs/nfs4proc.c | 25 +++++++++++++++++--------
 1 file changed, 17 insertions(+), 8 deletions(-)

diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index c53ddb185aa3..ec1ce593dea2 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4533,12 +4533,17 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
 	status = nfs4_do_call_sync(server->client, server, &msg,
 				   &args.seq_args, &res.seq_res, task_flags);
 	if (args.get_dir_deleg) {
-		if (status == -EOPNOTSUPP) {
+		switch (status) {
+		case 0:
+			if (gdd_res.status != GDD4_OK)
+				break;
+			status = nfs_inode_set_delegation(
+				inode, current_cred(), FMODE_READ,
+				&gdd_res.deleg, 0, NFS4_OPEN_DELEGATE_READ);
+			break;
+		case -ENOTSUPP:
+		case -EOPNOTSUPP:
 			server->caps &= ~NFS_CAP_DIR_DELEG;
-		} else if (status == 0 && gdd_res.status == GDD4_OK) {
-			status = nfs_inode_set_delegation(inode, current_cred(),
-							  FMODE_READ, &gdd_res.deleg,
-							  0, NFS4_OPEN_DELEGATE_READ);
 		}
 	}
 	return status;
@@ -4554,10 +4559,14 @@ int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
 	do {
 		err = _nfs4_proc_getattr(server, fhandle, fattr, inode);
 		trace_nfs4_getattr(server, fhandle, fattr, err);
-		if (err == -EOPNOTSUPP)
-			exception.retry = true;
-		else
+		switch (err) {
+		default:
 			err = nfs4_handle_exception(server, err, &exception);
+			break;
+		case -ENOTSUPP:
+		case -EOPNOTSUPP:
+			exception.retry = true;
+		}
 	} while (exception.retry);
 	return err;
 }
-- 
2.52.0


-- 
Trond Myklebust
Linux NFS client maintainer, Hammerspace
trondmy@kernel.org, trond.myklebust@hammerspace.com

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

* Re: [PATCH 2/5] NFS: Request a directory delegation on ACCESS, CREATE, and UNLINK
  2025-12-03 16:23       ` Trond Myklebust
@ 2025-12-03 21:06         ` Jon Hunter
  2025-12-03 23:19           ` Trond Myklebust
  0 siblings, 1 reply; 11+ messages in thread
From: Jon Hunter @ 2025-12-03 21:06 UTC (permalink / raw)
  To: Trond Myklebust, Anna Schumaker, linux-nfs; +Cc: linux-tegra@vger.kernel.org

Hi Trond,

On 03/12/2025 16:23, Trond Myklebust wrote:
> Hi Jon,
> 
> On Wed, 2025-12-03 at 15:56 +0000, Jon Hunter wrote:
>>
>> On 02/12/2025 16:01, Jon Hunter wrote:
>>> Hi Anna,
>>>
>>> On 04/11/2025 15:06, Anna Schumaker wrote:
>>>> From: Anna Schumaker <anna.schumaker@oracle.com>
>>>>
>>>> This patch adds a new flag: NFS_INO_REQ_DIR_DELEG to signal that
>>>> a
>>>> directory wants to request a directory delegation the next time
>>>> it does
>>>> a GETATTR. I have the client request a directory delegation when
>>>> doing
>>>> an access, create, or unlink call since these calls indicate that
>>>> a user
>>>> is working with a directory.
>>>>
>>>> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
>>>
>>>
>>> We use NFS for boot testing our boards and once this commit landed
>>> in -
>>> next a lot of them, but no all, started failing to boot. Bisect is
>>> pointing to this change.
>>>
>>> We have a custom init script that runs to mount the rootfs and I
>>> see
>>> that it displays ...
>>>
>>> [   10.238091] Run /init as init process
>>> [   10.266026] ERROR: mounting debugfs fail...
>>> [   10.286535] Root device found: nfs
>>> [   10.300342] Ethernet interface: eth0
>>> [   10.313920] IP Address: 192.168.99.2
>>> [   10.382738] Rootfs mounted over nfs
>>> [   10.416010] Switching from initrd to actual rootfs
>>
>> It appears that there are multiple boot issues on -next at the moment
>> and the above it not the relevant part for this particular issue.
>> Looking further at the logs I am seeing the following errors which
>> are related to this change ...
>>
>> [   11.100334] systemd[1]: Failed to open directory
>> /etc/systemd/system, ignoring: Unknown error 524
>> [   11.119234] systemd[1]: Failed to open directory
>> /lib/systemd/system, ignoring: Unknown error 524
>> [   11.143487] systemd[1]: Failed to load default target: No such
>> file or directory
>> [   11.158620] systemd[1]: Trying to load rescue target...
>> [   11.169388] systemd[1]: Failed to load rescue target: No such file
>> or directory
>> [   11.188856] systemd[1]: Freezing execution.
>>
>> Thanks
>> Jon
> 
> Does the following patch fix it for you?
> 
> 8<---------------------------------------------
>  From 849bdbd3a2136a86c809ce6a7fa6ae30e9f0728a Mon Sep 17 00:00:00 2001
> Message-ID: <849bdbd3a2136a86c809ce6a7fa6ae30e9f0728a.1764778907.git.trond.myklebust@hammerspace.com>
> From: Trond Myklebust <trond.myklebust@hammerspace.com>
> Date: Wed, 3 Dec 2025 11:17:25 -0500
> Subject: [PATCH] NFSv4: Handle NFS4ERR_NOTSUPP errors for directory
>   delegations
> 
> The error NFS4ERR_NOTSUPP will be returned for operations that are
> legal, but not supported by the server.
> 
> Fixes: 156b09482933 ("NFS: Request a directory delegation on ACCESS, CREATE, and UNLINK")
> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
> ---
>   fs/nfs/nfs4proc.c | 25 +++++++++++++++++--------
>   1 file changed, 17 insertions(+), 8 deletions(-)
> 
> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> index c53ddb185aa3..ec1ce593dea2 100644
> --- a/fs/nfs/nfs4proc.c
> +++ b/fs/nfs/nfs4proc.c
> @@ -4533,12 +4533,17 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
>   	status = nfs4_do_call_sync(server->client, server, &msg,
>   				   &args.seq_args, &res.seq_res, task_flags);
>   	if (args.get_dir_deleg) {
> -		if (status == -EOPNOTSUPP) {
> +		switch (status) {
> +		case 0:
> +			if (gdd_res.status != GDD4_OK)
> +				break;
> +			status = nfs_inode_set_delegation(
> +				inode, current_cred(), FMODE_READ,
> +				&gdd_res.deleg, 0, NFS4_OPEN_DELEGATE_READ);
> +			break;
> +		case -ENOTSUPP:
> +		case -EOPNOTSUPP:
>   			server->caps &= ~NFS_CAP_DIR_DELEG;
> -		} else if (status == 0 && gdd_res.status == GDD4_OK) {
> -			status = nfs_inode_set_delegation(inode, current_cred(),
> -							  FMODE_READ, &gdd_res.deleg,
> -							  0, NFS4_OPEN_DELEGATE_READ);
>   		}
>   	}
>   	return status;
> @@ -4554,10 +4559,14 @@ int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
>   	do {
>   		err = _nfs4_proc_getattr(server, fhandle, fattr, inode);
>   		trace_nfs4_getattr(server, fhandle, fattr, err);
> -		if (err == -EOPNOTSUPP)
> -			exception.retry = true;
> -		else
> +		switch (err) {
> +		default:
>   			err = nfs4_handle_exception(server, err, &exception);
> +			break;
> +		case -ENOTSUPP:
> +		case -EOPNOTSUPP:
> +			exception.retry = true;
> +		}
>   	} while (exception.retry);
>   	return err;
>   }

Yes that does appear to fix it thanks!

Cheers
Jon

-- 
nvpublic


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

* Re: [PATCH 2/5] NFS: Request a directory delegation on ACCESS, CREATE, and UNLINK
  2025-12-03 21:06         ` Jon Hunter
@ 2025-12-03 23:19           ` Trond Myklebust
  0 siblings, 0 replies; 11+ messages in thread
From: Trond Myklebust @ 2025-12-03 23:19 UTC (permalink / raw)
  To: Jon Hunter, Anna Schumaker, linux-nfs; +Cc: linux-tegra@vger.kernel.org

On Wed, 2025-12-03 at 21:06 +0000, Jon Hunter wrote:
> Hi Trond,
> 
<snip>
> 
> Yes that does appear to fix it thanks!

Thanks for testing! I'm pushing that fix out to the linux-next branch.

-- 
Trond Myklebust
Linux NFS client maintainer, Hammerspace
trondmy@kernel.org, trond.myklebust@hammerspace.com

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

end of thread, other threads:[~2025-12-03 23:19 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-04 15:06 [PATCH 0/5] NFS: Client Side Directory Delegations Anna Schumaker
2025-11-04 15:06 ` [PATCH 1/5] NFS: Add support for sending GDD_GETATTR Anna Schumaker
2025-11-04 15:06 ` [PATCH 2/5] NFS: Request a directory delegation on ACCESS, CREATE, and UNLINK Anna Schumaker
2025-12-02 16:01   ` Jon Hunter
2025-12-03 15:56     ` Jon Hunter
2025-12-03 16:23       ` Trond Myklebust
2025-12-03 21:06         ` Jon Hunter
2025-12-03 23:19           ` Trond Myklebust
2025-11-04 15:06 ` [PATCH 3/5] NFS: Request a directory delegation during RENAME Anna Schumaker
2025-11-04 15:06 ` [PATCH 4/5] NFS: Shortcut lookup revalidations if we have a directory delegation Anna Schumaker
2025-11-04 15:06 ` [PATCH 5/5] NFS: Add a module option to disable directory delegations Anna Schumaker

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