]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
NFS: Shortcut lookup revalidations if we have a directory delegation
authorAnna Schumaker <anna.schumaker@oracle.com>
Tue, 4 Nov 2025 15:06:44 +0000 (10:06 -0500)
committerTrond Myklebust <trond.myklebust@hammerspace.com>
Sun, 23 Nov 2025 21:01:47 +0000 (16:01 -0500)
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>
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
fs/nfs/delegation.h
fs/nfs/dir.c
fs/nfs/inode.c

index def50e8a83bf5f2f5790ccb20f50c696388574fa..8968f62bf438dbec42243a7e47a736e83f69a40b 100644 (file)
@@ -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
index 3b8250ee014126d54139297fc9c06b91352193db..23a78a742b619dea8b76ddf28f4f59a1c8a015e2 100644 (file)
@@ -1515,6 +1515,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)
@@ -2207,6 +2216,13 @@ no_open:
 }
 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)
@@ -2234,6 +2250,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;
index 13ad70fc00d84bdc2ab96c53237e8b1917431c39..2060adb3b0c5be909a1ed72149c965e62000a453 100644 (file)
@@ -1389,6 +1389,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;