Commit 16e14375 authored by Trond Myklebust's avatar Trond Myklebust Committed by Anna Schumaker

NFS: More fine grained attribute tracking

Currently, if the NFS_INO_INVALID_ATTR flag is set, for instance by
a call to nfs_post_op_update_inode_locked(), then it will not be cleared
until all the attributes have been revalidated. This means, for instance,
that NFSv4 writes will always force a full attribute revalidation.

Track the ctime, mtime, size and change attribute separately from the
other attributes so that we can have nfs_post_op_update_inode_locked()
set them correctly, and later have the cache consistency bitmask be
able to clear them.
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent cac88f94
...@@ -1272,7 +1272,9 @@ static void nfs_drop_nlink(struct inode *inode) ...@@ -1272,7 +1272,9 @@ static void nfs_drop_nlink(struct inode *inode)
/* drop the inode if we're reasonably sure this is the last link */ /* drop the inode if we're reasonably sure this is the last link */
if (inode->i_nlink == 1) if (inode->i_nlink == 1)
clear_nlink(inode); clear_nlink(inode);
NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATTR; NFS_I(inode)->cache_validity |= NFS_INO_INVALID_CHANGE
| NFS_INO_INVALID_CTIME
| NFS_INO_INVALID_OTHER;
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
} }
......
This diff is collapsed.
...@@ -1045,7 +1045,9 @@ static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo, ...@@ -1045,7 +1045,9 @@ static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo,
struct nfs_inode *nfsi = NFS_I(dir); struct nfs_inode *nfsi = NFS_I(dir);
spin_lock(&dir->i_lock); spin_lock(&dir->i_lock);
nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; nfsi->cache_validity |= NFS_INO_INVALID_CTIME
| NFS_INO_INVALID_MTIME
| NFS_INO_INVALID_DATA;
if (cinfo->atomic && cinfo->before == inode_peek_iversion_raw(dir)) { if (cinfo->atomic && cinfo->before == inode_peek_iversion_raw(dir)) {
nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE; nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE;
nfsi->attrtimeo_timestamp = jiffies; nfsi->attrtimeo_timestamp = jiffies;
...@@ -5364,7 +5366,8 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl ...@@ -5364,7 +5366,8 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
* so mark the attribute cache invalid. * so mark the attribute cache invalid.
*/ */
spin_lock(&inode->i_lock); spin_lock(&inode->i_lock);
NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATTR; NFS_I(inode)->cache_validity |= NFS_INO_INVALID_CHANGE
| NFS_INO_INVALID_CTIME;
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
nfs_access_zap_cache(inode); nfs_access_zap_cache(inode);
nfs_zap_acl_cache(inode); nfs_zap_acl_cache(inode);
......
...@@ -1562,8 +1562,11 @@ static int nfs_writeback_done(struct rpc_task *task, ...@@ -1562,8 +1562,11 @@ static int nfs_writeback_done(struct rpc_task *task,
} }
/* Deal with the suid/sgid bit corner case */ /* Deal with the suid/sgid bit corner case */
if (nfs_should_remove_suid(inode)) if (nfs_should_remove_suid(inode)) {
nfs_mark_for_revalidate(inode); spin_lock(&inode->i_lock);
NFS_I(inode)->cache_validity |= NFS_INO_INVALID_OTHER;
spin_unlock(&inode->i_lock);
}
return 0; return 0;
} }
......
...@@ -198,7 +198,6 @@ struct nfs_inode { ...@@ -198,7 +198,6 @@ struct nfs_inode {
/* /*
* Cache validity bit flags * Cache validity bit flags
*/ */
#define NFS_INO_INVALID_ATTR BIT(0) /* cached attrs are invalid */
#define NFS_INO_INVALID_DATA BIT(1) /* cached data is invalid */ #define NFS_INO_INVALID_DATA BIT(1) /* cached data is invalid */
#define NFS_INO_INVALID_ATIME BIT(2) /* cached atime is invalid */ #define NFS_INO_INVALID_ATIME BIT(2) /* cached atime is invalid */
#define NFS_INO_INVALID_ACCESS BIT(3) /* cached access cred invalid */ #define NFS_INO_INVALID_ACCESS BIT(3) /* cached access cred invalid */
...@@ -206,6 +205,17 @@ struct nfs_inode { ...@@ -206,6 +205,17 @@ struct nfs_inode {
#define NFS_INO_REVAL_PAGECACHE BIT(5) /* must revalidate pagecache */ #define NFS_INO_REVAL_PAGECACHE BIT(5) /* must revalidate pagecache */
#define NFS_INO_REVAL_FORCED BIT(6) /* force revalidation ignoring a delegation */ #define NFS_INO_REVAL_FORCED BIT(6) /* force revalidation ignoring a delegation */
#define NFS_INO_INVALID_LABEL BIT(7) /* cached label is invalid */ #define NFS_INO_INVALID_LABEL BIT(7) /* cached label is invalid */
#define NFS_INO_INVALID_CHANGE BIT(8) /* cached change is invalid */
#define NFS_INO_INVALID_CTIME BIT(9) /* cached ctime 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_OTHER BIT(12) /* other attrs are invalid */
#define NFS_INO_INVALID_ATTR (NFS_INO_INVALID_CHANGE \
| NFS_INO_INVALID_CTIME \
| NFS_INO_INVALID_MTIME \
| NFS_INO_INVALID_SIZE \
| NFS_INO_INVALID_OTHER) /* inode metadata is invalid */
/* /*
* Bit offsets in flags field * Bit offsets in flags field
...@@ -292,10 +302,11 @@ static inline void nfs_mark_for_revalidate(struct inode *inode) ...@@ -292,10 +302,11 @@ static inline void nfs_mark_for_revalidate(struct inode *inode)
struct nfs_inode *nfsi = NFS_I(inode); struct nfs_inode *nfsi = NFS_I(inode);
spin_lock(&inode->i_lock); spin_lock(&inode->i_lock);
nfsi->cache_validity |= NFS_INO_INVALID_ATTR | nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE
NFS_INO_REVAL_PAGECACHE | | NFS_INO_INVALID_ACCESS
NFS_INO_INVALID_ACCESS | | NFS_INO_INVALID_ACL
NFS_INO_INVALID_ACL; | NFS_INO_INVALID_CHANGE
| NFS_INO_INVALID_CTIME;
if (S_ISDIR(inode->i_mode)) if (S_ISDIR(inode->i_mode))
nfsi->cache_validity |= NFS_INO_INVALID_DATA; nfsi->cache_validity |= NFS_INO_INVALID_DATA;
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
......
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