Commit 1c341b77 authored by Trond Myklebust's avatar Trond Myklebust

NFS: Add deferred cache invalidation for close-to-open consistency violations

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: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
parent 44942b4e
...@@ -80,6 +80,10 @@ static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct inode *dir ...@@ -80,6 +80,10 @@ static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct inode *dir
ctx->dup_cookie = 0; ctx->dup_cookie = 0;
ctx->cred = get_cred(cred); ctx->cred = get_cred(cred);
spin_lock(&dir->i_lock); 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); list_add(&ctx->list, &nfsi->open_files);
spin_unlock(&dir->i_lock); spin_unlock(&dir->i_lock);
return ctx; return ctx;
......
...@@ -208,7 +208,7 @@ static void nfs_set_cache_invalid(struct inode *inode, unsigned long flags) ...@@ -208,7 +208,7 @@ static void nfs_set_cache_invalid(struct inode *inode, unsigned long flags)
} }
if (inode->i_mapping->nrpages == 0) 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; nfsi->cache_validity |= flags;
if (flags & NFS_INO_INVALID_DATA) if (flags & NFS_INO_INVALID_DATA)
nfs_fscache_invalidate(inode); nfs_fscache_invalidate(inode);
...@@ -652,7 +652,8 @@ static int nfs_vmtruncate(struct inode * inode, loff_t offset) ...@@ -652,7 +652,8 @@ static int nfs_vmtruncate(struct inode * inode, loff_t offset)
i_size_write(inode, offset); i_size_write(inode, offset);
/* Optimisation */ /* Optimisation */
if (offset == 0) 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; NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_SIZE;
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
...@@ -1032,6 +1033,10 @@ void nfs_inode_attach_open_context(struct nfs_open_context *ctx) ...@@ -1032,6 +1033,10 @@ void nfs_inode_attach_open_context(struct nfs_open_context *ctx)
struct nfs_inode *nfsi = NFS_I(inode); struct nfs_inode *nfsi = NFS_I(inode);
spin_lock(&inode->i_lock); 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); list_add_tail_rcu(&ctx->list, &nfsi->open_files);
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
} }
...@@ -1313,7 +1318,8 @@ int nfs_revalidate_mapping(struct inode *inode, ...@@ -1313,7 +1318,8 @@ int nfs_revalidate_mapping(struct inode *inode,
set_bit(NFS_INO_INVALIDATING, bitlock); set_bit(NFS_INO_INVALIDATING, bitlock);
smp_wmb(); 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); spin_unlock(&inode->i_lock);
trace_nfs_invalidate_mapping_enter(inode); trace_nfs_invalidate_mapping_enter(inode);
ret = nfs_invalidate_mapping(inode, mapping); ret = nfs_invalidate_mapping(inode, mapping);
...@@ -1871,7 +1877,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) ...@@ -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", dprintk("NFS: change_attr change on server for file %s/%ld\n",
inode->i_sb->s_id, inode->i_sb->s_id,
inode->i_ino); inode->i_ino);
} } else if (!have_delegation)
nfsi->cache_validity |= NFS_INO_DATA_INVAL_DEFER;
inode_set_iversion_raw(inode, fattr->change_attr); inode_set_iversion_raw(inode, fattr->change_attr);
attr_changed = true; attr_changed = true;
} }
......
...@@ -223,6 +223,8 @@ struct nfs4_copy_state { ...@@ -223,6 +223,8 @@ struct nfs4_copy_state {
#define NFS_INO_INVALID_MTIME BIT(10) /* cached mtime is invalid */ #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_SIZE BIT(11) /* cached size is invalid */
#define NFS_INO_INVALID_OTHER BIT(12) /* other attrs are 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 \ #define NFS_INO_INVALID_ATTR (NFS_INO_INVALID_CHANGE \
| NFS_INO_INVALID_CTIME \ | NFS_INO_INVALID_CTIME \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment