NFS: Add deferred cache invalidation for close-to-open consistency violations
authorTrond Myklebust <trond.myklebust@hammerspace.com>
Wed, 22 May 2019 12:38:57 +0000 (08:38 -0400)
committerTrond Myklebust <trond.myklebust@hammerspace.com>
Sat, 6 Jul 2019 18:54:49 +0000 (14:54 -0400)
If the client detects that close-to-open cache consistency has been
violated, and that the file or directory has been changed on the
server, then do a cache invalidation when we're done working with
the file.
The reason we don't do an immediate cache invalidation is that we
want to avoid performance problems due to false positives. Also,
note that we cannot guarantee cache consistency in this situation
even if we do invalidate the cache.

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

index 57b6a45576adf028ee056c8c7bcf54707446e968..bd1f9555447bbcd0ab7254638cafaa634f6a36b5 100644 (file)
@@ -80,6 +80,10 @@ static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct inode *dir
                ctx->dup_cookie = 0;
                ctx->cred = get_cred(cred);
                spin_lock(&dir->i_lock);
+               if (list_empty(&nfsi->open_files) &&
+                   (nfsi->cache_validity & NFS_INO_DATA_INVAL_DEFER))
+                       nfsi->cache_validity |= NFS_INO_INVALID_DATA |
+                               NFS_INO_REVAL_FORCED;
                list_add(&ctx->list, &nfsi->open_files);
                spin_unlock(&dir->i_lock);
                return ctx;
index 53777813ca95fbf0facd0b7be9d5e9eb542d9500..ea52c71534b5c5c9da134067b7e0d0ae97279658 100644 (file)
@@ -208,7 +208,7 @@ static void nfs_set_cache_invalid(struct inode *inode, unsigned long flags)
        }
 
        if (inode->i_mapping->nrpages == 0)
-               flags &= ~NFS_INO_INVALID_DATA;
+               flags &= ~(NFS_INO_INVALID_DATA|NFS_INO_DATA_INVAL_DEFER);
        nfsi->cache_validity |= flags;
        if (flags & NFS_INO_INVALID_DATA)
                nfs_fscache_invalidate(inode);
@@ -652,7 +652,8 @@ static int nfs_vmtruncate(struct inode * inode, loff_t offset)
        i_size_write(inode, offset);
        /* Optimisation */
        if (offset == 0)
-               NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_DATA;
+               NFS_I(inode)->cache_validity &= ~(NFS_INO_INVALID_DATA |
+                               NFS_INO_DATA_INVAL_DEFER);
        NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_SIZE;
 
        spin_unlock(&inode->i_lock);
@@ -1032,6 +1033,10 @@ void nfs_inode_attach_open_context(struct nfs_open_context *ctx)
        struct nfs_inode *nfsi = NFS_I(inode);
 
        spin_lock(&inode->i_lock);
+       if (list_empty(&nfsi->open_files) &&
+           (nfsi->cache_validity & NFS_INO_DATA_INVAL_DEFER))
+               nfsi->cache_validity |= NFS_INO_INVALID_DATA |
+                       NFS_INO_REVAL_FORCED;
        list_add_tail_rcu(&ctx->list, &nfsi->open_files);
        spin_unlock(&inode->i_lock);
 }
@@ -1313,7 +1318,8 @@ int nfs_revalidate_mapping(struct inode *inode,
 
        set_bit(NFS_INO_INVALIDATING, bitlock);
        smp_wmb();
-       nfsi->cache_validity &= ~NFS_INO_INVALID_DATA;
+       nfsi->cache_validity &= ~(NFS_INO_INVALID_DATA|
+                       NFS_INO_DATA_INVAL_DEFER);
        spin_unlock(&inode->i_lock);
        trace_nfs_invalidate_mapping_enter(inode);
        ret = nfs_invalidate_mapping(inode, mapping);
@@ -1871,7 +1877,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
                                dprintk("NFS: change_attr change on server for file %s/%ld\n",
                                                inode->i_sb->s_id,
                                                inode->i_ino);
-                       }
+                       } else if (!have_delegation)
+                               nfsi->cache_validity |= NFS_INO_DATA_INVAL_DEFER;
                        inode_set_iversion_raw(inode, fattr->change_attr);
                        attr_changed = true;
                }
index d363d5765cdf70f850fc28bfb359f82d6f44a9f1..0a11712a80e37cfe18a108f43a58cbf3842b63c7 100644 (file)
@@ -223,6 +223,8 @@ struct nfs4_copy_state {
 #define NFS_INO_INVALID_MTIME  BIT(10)         /* cached mtime is invalid */
 #define NFS_INO_INVALID_SIZE   BIT(11)         /* cached size is invalid */
 #define NFS_INO_INVALID_OTHER  BIT(12)         /* other attrs are invalid */
+#define NFS_INO_DATA_INVAL_DEFER       \
+                               BIT(13)         /* Deferred cache invalidation */
 
 #define NFS_INO_INVALID_ATTR   (NFS_INO_INVALID_CHANGE \
                | NFS_INO_INVALID_CTIME \