NFS: Only look at the change attribute cache state in nfs_check_verifier
authorTrond Myklebust <trond.myklebust@primarydata.com>
Sun, 4 Dec 2016 23:34:34 +0000 (18:34 -0500)
committerTrond Myklebust <trond.myklebust@primarydata.com>
Sun, 4 Dec 2016 23:34:34 +0000 (18:34 -0500)
When looking at whether or not our dcache is valid, we really don't care
about the general state of the directory attribute cache. Instead, we
we only care about the state of the change attribute.

This fixes a performance issue when the client is responsible for
changing the directory contents; a number of NFSv4 operations will
atomically update the directory change attribute, but may not return
all the other attributes.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
fs/nfs/dir.c
fs/nfs/inode.c
include/linux/nfs_fs.h

index f5702457c05255cabb0e870626315931022f8580..7483722162fa0591e8ad2de2ac88687aed2d431e 100644 (file)
@@ -1030,8 +1030,6 @@ EXPORT_SYMBOL_GPL(nfs_force_lookup_revalidate);
 static int nfs_check_verifier(struct inode *dir, struct dentry *dentry,
                              int rcu_walk)
 {
-       int ret;
-
        if (IS_ROOT(dentry))
                return 1;
        if (NFS_SERVER(dir)->flags & NFS_MOUNT_LOOKUP_CACHE_NONE)
@@ -1039,12 +1037,12 @@ static int nfs_check_verifier(struct inode *dir, struct dentry *dentry,
        if (!nfs_verify_change_attribute(dir, dentry->d_time))
                return 0;
        /* Revalidate nfsi->cache_change_attribute before we declare a match */
-       if (rcu_walk)
-               ret = nfs_revalidate_inode_rcu(NFS_SERVER(dir), dir);
-       else
-               ret = nfs_revalidate_inode(NFS_SERVER(dir), dir);
-       if (ret < 0)
-               return 0;
+       if (nfs_mapping_need_revalidate_inode(dir)) {
+               if (rcu_walk)
+                       return 0;
+               if (__nfs_revalidate_inode(NFS_SERVER(dir), dir) < 0)
+                       return 0;
+       }
        if (!nfs_verify_change_attribute(dir, dentry->d_time))
                return 0;
        return 1;
index df4d7ec348ed922c07a726e8e3be1c6ccae9b7b2..7de345fd8e1eafba543313854831ca9e1aa9034a 100644 (file)
@@ -1112,7 +1112,7 @@ static int nfs_invalidate_mapping(struct inode *inode, struct address_space *map
        return 0;
 }
 
-static bool nfs_mapping_need_revalidate_inode(struct inode *inode)
+bool nfs_mapping_need_revalidate_inode(struct inode *inode)
 {
        unsigned long cache_validity = NFS_I(inode)->cache_validity;
 
index db1002abc95e7783520b0ada7d3e63c3a07c08ec..cb631973839a7ff7dd10a8426de10d3a30393e9a 100644 (file)
@@ -345,6 +345,7 @@ extern int nfs_attribute_cache_expired(struct inode *inode);
 extern int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode);
 extern int nfs_revalidate_inode_rcu(struct nfs_server *server, struct inode *inode);
 extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *);
+extern bool nfs_mapping_need_revalidate_inode(struct inode *inode);
 extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping);
 extern int nfs_revalidate_mapping_rcu(struct inode *inode);
 extern int nfs_setattr(struct dentry *, struct iattr *);